import CS libvirt-11.10.0-12.el10

This commit is contained in:
AlmaLinux RelEng Bot 2026-04-07 06:32:28 -04:00
parent b14161abef
commit 02eac15171
174 changed files with 32492 additions and 1770 deletions

2
.gitignore vendored
View File

@ -1 +1 @@
libvirt-10.5.0.tar.xz
libvirt-11.10.0.tar.xz

View File

@ -0,0 +1,248 @@
From 48f5933f6cd6f53997823cfe2a277b822b00264f Mon Sep 17 00:00:00 2001
Message-ID: <48f5933f6cd6f53997823cfe2a277b822b00264f.1771336681.git.jdenemar@redhat.com>
From: Peter Krempa <pkrempa@redhat.com>
Date: Thu, 29 Jan 2026 18:10:26 +0100
Subject: [PATCH] Expose latency histograms via 'virConnectGetAllDomainStats'
Add documentation and constants for constructing the stats field names
for latency histograms and expose them in the qemu driver:
Example:
block.1.latency_histogram.read.bin.count=9
block.1.latency_histogram.read.bin.0.start=0
block.1.latency_histogram.read.bin.0.value=0
block.1.latency_histogram.read.bin.1.start=10
block.1.latency_histogram.read.bin.1.value=0
block.1.latency_histogram.read.bin.2.start=100
block.1.latency_histogram.read.bin.2.value=0
block.1.latency_histogram.read.bin.3.start=1000
block.1.latency_histogram.read.bin.3.value=1047
block.1.latency_histogram.read.bin.4.start=10000
block.1.latency_histogram.read.bin.4.value=2131
block.1.latency_histogram.read.bin.5.start=100000
block.1.latency_histogram.read.bin.5.value=0
block.1.latency_histogram.read.bin.6.start=1000000
block.1.latency_histogram.read.bin.6.value=0
block.1.latency_histogram.read.bin.7.start=10000000
block.1.latency_histogram.read.bin.7.value=0
block.1.latency_histogram.read.bin.8.start=100000000
block.1.latency_histogram.read.bin.8.value=0
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit 237e49127a9390f054e33e689ba9db1587cdc9f1)
https://issues.redhat.com/browse/RHEL-147866 [rhel-9.8]
https://issues.redhat.com/browse/RHEL-131335 [rhel-10.2]
---
docs/manpages/virsh.rst | 7 ++
include/libvirt/libvirt-domain.h | 113 +++++++++++++++++++++++++++++++
src/qemu/qemu_driver.c | 43 ++++++++++++
3 files changed, 163 insertions(+)
diff --git a/docs/manpages/virsh.rst b/docs/manpages/virsh.rst
index a9d691824e..ff0cf1a715 100644
--- a/docs/manpages/virsh.rst
+++ b/docs/manpages/virsh.rst
@@ -2811,6 +2811,13 @@ Information listed includes:
pending write operations in the defined interval
* ``block.<num>.timed_group.<num>.zone_append_queue_depth_avg`` - average number
of pending zone append operations in the defined interval
+* ``block.<num>.latency_histogram.<type>.bin.count`` - number of bins in
+ latency histogram. <type> is one of ``read``, ``write``, ``zone_append``, or
+ ``flush``
+* ``block.<num>.latency_histogram.<type>.bin.<num>.start`` start boundary of
+ a latency histogram bin in nanoseconds of given operation duration
+* ``block.<num>.latency_histogram.<type>.bin.<num>.value`` current number of
+ events corresponding to the given bin and type
*--iothread* returns information about IOThreads on the running guest
diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h
index 16fac6b085..8e62bd23d4 100644
--- a/include/libvirt/libvirt-domain.h
+++ b/include/libvirt/libvirt-domain.h
@@ -3815,6 +3815,119 @@ struct _virDomainStatsRecord {
*/
# define VIR_DOMAIN_STATS_BLOCK_SUFFIX_TIMED_GROUP_SUFFIX_ZONE_APPEND_QUEUE_DEPTH_AVG ".zone_append_queue_depth_avg"
+/**
+ * VIR_DOMAIN_STATS_BLOCK_SUFFIX_LATENCY_HISTOGRAM_READ_PREFIX:
+ *
+ * The parameter name prefix to access 'read' latency histograms. Concatenate
+ * the prefix with either:
+ * - VIR_DOMAIN_STATS_BLOCK_SUFFIX_LATENCY_HISTOGRAM_SUFFIX_BIN_COUNT
+ * to get the number of bins in given histogram
+ * - VIR_DOMAIN_STATS_BLOCK_SUFFIX_LATENCY_HISTOGRAM_SUFFIX_BIN_PREFIX and
+ * entry number formatted as an unsigned integer and one of the latency
+ * histogram suffix parameters to compelte a full bin parameter name
+ *
+ * Since: 12.1.0
+ */
+# define VIR_DOMAIN_STATS_BLOCK_SUFFIX_LATENCY_HISTOGRAM_READ_PREFIX ".latency_histogram.read."
+
+/**
+ * VIR_DOMAIN_STATS_BLOCK_SUFFIX_LATENCY_HISTOGRAM_WRITE_PREFIX:
+ *
+ * The parameter name prefix to access 'write' latency histograms. Concatenate
+ * the prefix with either:
+ * - VIR_DOMAIN_STATS_BLOCK_SUFFIX_LATENCY_HISTOGRAM_SUFFIX_BIN_COUNT
+ * to get the number of bins in given histogram
+ * - VIR_DOMAIN_STATS_BLOCK_SUFFIX_LATENCY_HISTOGRAM_SUFFIX_BIN_PREFIX and
+ * entry number formatted as an unsigned integer and one of the latency
+ * histogram suffix parameters to compelte a full bin parameter name
+ *
+ * Since: 12.1.0
+ */
+# define VIR_DOMAIN_STATS_BLOCK_SUFFIX_LATENCY_HISTOGRAM_WRITE_PREFIX ".latency_histogram.write."
+
+/**
+ * VIR_DOMAIN_STATS_BLOCK_SUFFIX_LATENCY_HISTOGRAM_ZONE_APPEND_PREFIX:
+ *
+ * The parameter name prefix to access 'zone_append' latency histograms. Concatenate
+ * the prefix with either:
+ * - VIR_DOMAIN_STATS_BLOCK_SUFFIX_LATENCY_HISTOGRAM_SUFFIX_BIN_COUNT
+ * to get the number of bins in given histogram
+ * - VIR_DOMAIN_STATS_BLOCK_SUFFIX_LATENCY_HISTOGRAM_SUFFIX_BIN_PREFIX and
+ * entry number formatted as an unsigned integer and one of the latency
+ * histogram suffix parameters to compelte a full bin parameter name
+ *
+ * Since: 12.1.0
+ */
+# define VIR_DOMAIN_STATS_BLOCK_SUFFIX_LATENCY_HISTOGRAM_ZONE_APPEND_PREFIX ".latency_histogram.zone_append."
+
+/**
+ * VIR_DOMAIN_STATS_BLOCK_SUFFIX_LATENCY_HISTOGRAM_FLUSH_PREFIX:
+ *
+ * The parameter name prefix to access 'flush' latency histograms. Concatenate
+ * the prefix with either:
+ * - VIR_DOMAIN_STATS_BLOCK_SUFFIX_LATENCY_HISTOGRAM_SUFFIX_BIN_COUNT
+ * to get the number of bins in given histogram
+ * - VIR_DOMAIN_STATS_BLOCK_SUFFIX_LATENCY_HISTOGRAM_SUFFIX_BIN_PREFIX and
+ * entry number formatted as an unsigned integer and one of the latency
+ * histogram suffix parameters to compelte a full bin parameter name
+ *
+ * Since: 12.1.0
+ */
+# define VIR_DOMAIN_STATS_BLOCK_SUFFIX_LATENCY_HISTOGRAM_FLUSH_PREFIX ".latency_histogram.flush."
+
+/**
+ * VIR_DOMAIN_STATS_BLOCK_SUFFIX_LATENCY_HISTOGRAM_SUFFIX_BIN_COUNT:
+ *
+ * The parameter name suffix to access number of bins in one of the following
+ * latency histogram types:
+ * - VIR_DOMAIN_STATS_BLOCK_SUFFIX_LATENCY_HISTOGRAM_READ_PREFIX
+ * - VIR_DOMAIN_STATS_BLOCK_SUFFIX_LATENCY_HISTOGRAM_WRITE_PREFIX
+ * - VIR_DOMAIN_STATS_BLOCK_SUFFIX_LATENCY_HISTOGRAM_ZONE_APPEND_PREFIX
+ * - VIR_DOMAIN_STATS_BLOCK_SUFFIX_LATENCY_HISTOGRAM_FLUSH_PREFIX
+ *
+ * Number of bins in latency histogram as unsigned long long.
+ *
+ * Since: 12.1.0
+ */
+# define VIR_DOMAIN_STATS_BLOCK_SUFFIX_LATENCY_HISTOGRAM_SUFFIX_BIN_COUNT "bin.count"
+
+/**
+ * VIR_DOMAIN_STATS_BLOCK_SUFFIX_LATENCY_HISTOGRAM_SUFFIX_BIN_PREFIX:
+ *
+ * The parameter name suffix to access a latency histogram bin in one of the
+ * following latency histogram types:
+ * - VIR_DOMAIN_STATS_BLOCK_SUFFIX_LATENCY_HISTOGRAM_READ_PREFIX
+ * - VIR_DOMAIN_STATS_BLOCK_SUFFIX_LATENCY_HISTOGRAM_WRITE_PREFIX
+ * - VIR_DOMAIN_STATS_BLOCK_SUFFIX_LATENCY_HISTOGRAM_ZONE_APPEND_PREFIX
+ * - VIR_DOMAIN_STATS_BLOCK_SUFFIX_LATENCY_HISTOGRAM_FLUSH_PREFIX
+ *
+ * Concatenate with a bin number as unsigned int and one of the other field
+ * suffixes to access bin parameters.
+ *
+ * Since: 12.1.0
+ */
+# define VIR_DOMAIN_STATS_BLOCK_SUFFIX_LATENCY_HISTOGRAM_SUFFIX_BIN_PREFIX "bin."
+
+/**
+ * VIR_DOMAIN_STATS_BLOCK_SUFFIX_LATENCY_HISTOGRAM_SUFFIX_BIN_SUFFIX_START:
+ *
+ * Start of the current latency histogram bin in nanoseconds as unsigned long long.
+ *
+ * Since: 12.1.0
+ */
+# define VIR_DOMAIN_STATS_BLOCK_SUFFIX_LATENCY_HISTOGRAM_SUFFIX_BIN_SUFFIX_START ".start"
+
+/**
+ * VIR_DOMAIN_STATS_BLOCK_SUFFIX_LATENCY_HISTOGRAM_SUFFIX_BIN_SUFFIX_VALUE:
+ *
+ * Current value of the number of occurences of the latency within this bin
+ * as unsigned long long.
+ *
+ * Since: 12.1.0
+ */
+# define VIR_DOMAIN_STATS_BLOCK_SUFFIX_LATENCY_HISTOGRAM_SUFFIX_BIN_SUFFIX_VALUE ".value"
+
+
/**
* VIR_DOMAIN_STATS_PERF_CMT:
*
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 08a547c546..f3e7410f9e 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -17597,6 +17597,36 @@ qemuDomainGetStatsBlockExportBackendStorage(const char *entryname,
}
+static void
+qemuDomainGetStatsBlockExportFrontendLatencyHistogram(struct qemuBlockStatsLatencyHistogram *h,
+ size_t disk_idx,
+ const char *prefix_hist,
+ virTypedParamList *par)
+{
+ size_t i;
+
+ if (!h)
+ return;
+
+ virTypedParamListAddULLong(par, h->nbins,
+ VIR_DOMAIN_STATS_BLOCK_PREFIX "%zu%s" VIR_DOMAIN_STATS_BLOCK_SUFFIX_LATENCY_HISTOGRAM_SUFFIX_BIN_COUNT,
+ disk_idx, prefix_hist);
+
+ for (i = 0; i < h->nbins; i++) {
+ virTypedParamListAddULLong(par, h->bins[i].start,
+ VIR_DOMAIN_STATS_BLOCK_PREFIX "%zu%s"
+ VIR_DOMAIN_STATS_BLOCK_SUFFIX_LATENCY_HISTOGRAM_SUFFIX_BIN_PREFIX "%zu"
+ VIR_DOMAIN_STATS_BLOCK_SUFFIX_LATENCY_HISTOGRAM_SUFFIX_BIN_SUFFIX_START,
+ disk_idx, prefix_hist, i);
+ virTypedParamListAddULLong(par, h->bins[i].value,
+ VIR_DOMAIN_STATS_BLOCK_PREFIX "%zu%s"
+ VIR_DOMAIN_STATS_BLOCK_SUFFIX_LATENCY_HISTOGRAM_SUFFIX_BIN_PREFIX "%zu"
+ VIR_DOMAIN_STATS_BLOCK_SUFFIX_LATENCY_HISTOGRAM_SUFFIX_BIN_SUFFIX_VALUE,
+ disk_idx, prefix_hist, i);
+ }
+}
+
+
static void
qemuDomainGetStatsBlockExportFrontend(const char *frontendname,
GHashTable *stats,
@@ -17721,6 +17751,19 @@ qemuDomainGetStatsBlockExportFrontend(const char *frontendname,
idx, i);
}
}
+
+ qemuDomainGetStatsBlockExportFrontendLatencyHistogram(en->histogram_read, idx,
+ VIR_DOMAIN_STATS_BLOCK_SUFFIX_LATENCY_HISTOGRAM_READ_PREFIX,
+ par);
+ qemuDomainGetStatsBlockExportFrontendLatencyHistogram(en->histogram_write, idx,
+ VIR_DOMAIN_STATS_BLOCK_SUFFIX_LATENCY_HISTOGRAM_WRITE_PREFIX,
+ par);
+ qemuDomainGetStatsBlockExportFrontendLatencyHistogram(en->histogram_zone, idx,
+ VIR_DOMAIN_STATS_BLOCK_SUFFIX_LATENCY_HISTOGRAM_ZONE_APPEND_PREFIX,
+ par);
+ qemuDomainGetStatsBlockExportFrontendLatencyHistogram(en->histogram_flush, idx,
+ VIR_DOMAIN_STATS_BLOCK_SUFFIX_LATENCY_HISTOGRAM_FLUSH_PREFIX,
+ par);
}
--
2.53.0

View File

@ -0,0 +1,422 @@
From 8fbea435edb1635ec98c9419e9249223e5c3b2b6 Mon Sep 17 00:00:00 2001
Message-ID: <8fbea435edb1635ec98c9419e9249223e5c3b2b6.1771336682.git.jdenemar@redhat.com>
From: Peter Krempa <pkrempa@redhat.com>
Date: Fri, 23 Jan 2026 17:09:27 +0100
Subject: [PATCH] Introduce support for disk operation latency histogram
collection
Add config and docs allowing enabling latency histogram collection for
block device operations.
This patch sets up the docs, schema and XML infrastructure.
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit b874c944bd8c4ffa6c51394557587c8c203f1656)
https://issues.redhat.com/browse/RHEL-147866 [rhel-9.8]
https://issues.redhat.com/browse/RHEL-131335 [rhel-10.2]
---
docs/formatdomain.rst | 41 ++++++
src/conf/domain_conf.c | 133 +++++++++++++++++-
src/conf/domain_conf.h | 7 +
src/conf/schemas/domaincommon.rng | 37 ++++-
...isk-statistics-intervals.x86_64-latest.xml | 29 ++++
.../disk-statistics-intervals.xml | 25 ++++
6 files changed, 262 insertions(+), 10 deletions(-)
diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst
index 70882c6820..31232deb3c 100644
--- a/docs/formatdomain.rst
+++ b/docs/formatdomain.rst
@@ -3628,6 +3628,47 @@ paravirtualized driver is specified via the ``disk`` element.
:since:`Since 11.9.0 (QEMU 10.2, virtio, ide, scsi disks only)`.
+ Block operation latency histogram collection can be configured using
+ ``<latency-histogram>`` sub-element. The histogram is collected for
+ the whole runtime of the VM, but can be re-started or reconfigured using
+ the `virDomainUpdateDeviceFlags <html/libvirt-libvirt-domain.html#virDomainUpdateDeviceFlags>`__
+ API. Using the same config re-starts histogram collection.
+
+ The optional ``type`` attribute configures specific operation to collect
+ the histogram for. Supported types are ``read``, ``write``, ``zone``, and
+ ``flush``. If the ``type`` attribute is omitted the histogram collection
+ bins bins apply to all of the aforementioned types, which can be overriden
+ with specific config.
+
+ The ``<latency-histogram>`` has multiple mandatory ``<bin>`` sub-elements
+ with mandatory ``start`` attribute configuring the starting boundary of
+ the histogram bin configured in nanosecods of the operation duration and
+ the intervals must be properly ordered and non-duplicate.
+
+ Example::
+
+ <driver name='qemu'>
+ <statistics>
+
+ <latency-histogram>
+ <bin start='0'/>
+ <bin start='1000'/>
+ <bin start='100000'/>
+ </latency-histogram>
+
+ [or for specific operation types]
+
+ <latency-histogram type='read'>
+ <bin start='0'/>
+ <bin start='1000'/>
+ <bin start='100000'/>
+ </latency-histogram>
+
+ </statistics>
+ </driver>
+
+ :since:`Since 12.1.0`.
+
- The optional ``queues`` attribute specifies the number of virt queues for
virtio-blk ( :since:`Since 3.9.0` ) or vhost-user-blk
( :since:`Since 7.1.0` )
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index f5c4d135a9..83c58ab5ff 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -2445,6 +2445,11 @@ virDomainDiskDefFree(virDomainDiskDef *def)
virObjectUnref(def->privateData);
g_slist_free_full(def->iothreads, (GDestroyNotify) virDomainIothreadMappingDefFree);
g_free(def->statistics);
+ g_free(def->histogram_boundaries);
+ g_free(def->histogram_boundaries_read);
+ g_free(def->histogram_boundaries_write);
+ g_free(def->histogram_boundaries_zone);
+ g_free(def->histogram_boundaries_flush);
if (def->throttlefilters) {
size_t i;
@@ -8307,6 +8312,91 @@ virDomainIothreadMappingDefParse(xmlNodePtr driverNode,
}
+static int
+virDomainDiskDefDriverParseXMLHistogramOne(virDomainDiskDef *def,
+ xmlNodePtr cur)
+{
+ g_autofree char *histogram_type = NULL;
+ unsigned int **histogram_config = NULL;
+ g_autoptr(GPtrArray) binNodes = virXMLNodeGetSubelementList(cur, "bin");
+ size_t nbins = 0;
+ size_t i;
+
+ if ((histogram_type = virXMLPropString(cur, "type"))) {
+ if (STREQ(histogram_type, "read")) {
+ histogram_config = &def->histogram_boundaries_read;
+ } else if (STREQ(histogram_type, "write")) {
+ histogram_config = &def->histogram_boundaries_write;
+ } else if (STREQ(histogram_type, "zone")) {
+ histogram_config = &def->histogram_boundaries_zone;
+ } else if (STREQ(histogram_type, "flush")) {
+ histogram_config = &def->histogram_boundaries_flush;
+ } else {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("unknown latency_histogram type '%1$s'"),
+ histogram_type);
+ return -1;
+ }
+ } else {
+ histogram_config = &def->histogram_boundaries;
+ }
+
+ if (*histogram_config) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("only one latency-histogram of a given type is supported"));
+ return -1;
+ }
+
+ if (binNodes->len == 0) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("missing 'bin' elements for 'latency-histogram'"));
+ return -1;
+ }
+
+ *histogram_config = g_new0(unsigned int, binNodes->len + 1);
+
+ for (i = 0; i < binNodes->len; i++) {
+ unsigned int val;
+
+ if (virXMLPropUInt(g_ptr_array_index(binNodes, i),
+ "start", 10,
+ VIR_XML_PROP_REQUIRED,
+ &val) < 0)
+ return -1;
+
+ if (nbins > 0 &&
+ (val == 0 ||
+ val <= (*histogram_config)[nbins-1])) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("the values of 'start' attribute of a 'latency-histogram' 'bin' configuration must be sorted and non-overlapping"));
+ return -1;
+ }
+
+ if (val > 0)
+ (*histogram_config)[nbins++] = val;
+ }
+
+ return 0;
+}
+
+
+static int
+virDomainDiskDefDriverParseXMLHistograms(virDomainDiskDef *def,
+ xmlNodePtr cur)
+{
+ g_autoptr(GPtrArray) histogramNodes = virXMLNodeGetSubelementList(cur, "latency-histogram");
+ size_t i;
+
+ for (i = 0; i < histogramNodes->len; i++) {
+ if (virDomainDiskDefDriverParseXMLHistogramOne(def,
+ g_ptr_array_index(histogramNodes, i)) < 0)
+ return -1;
+ }
+
+ return 0;
+}
+
+
static int
virDomainDiskDefDriverParseXML(virDomainDiskDef *def,
xmlNodePtr cur)
@@ -8380,6 +8470,9 @@ virDomainDiskDefDriverParseXML(virDomainDiskDef *def,
return -1;
}
}
+
+ if (virDomainDiskDefDriverParseXMLHistograms(def, statisticsNode) < 0)
+ return -1;
}
if (virXMLPropEnum(cur, "detect_zeroes",
@@ -23961,12 +24054,37 @@ virDomainDiskDefFormatThrottleFilters(virBuffer *buf,
}
+static void
+virDomainDiskDefFormatDriverHistogram(virBuffer *buf,
+ const char *type,
+ unsigned int *bins)
+{
+ g_auto(virBuffer) histogramAttrBuf = VIR_BUFFER_INITIALIZER;
+ g_auto(virBuffer) histogramChildBuf = VIR_BUFFER_INIT_CHILD(buf);
+
+ if (!bins || bins[0] == 0)
+ return;
+
+ if (type)
+ virBufferAsprintf(&histogramAttrBuf, " type='%s'", type);
+
+ /* we dont store the start boundary of the first bin but it's always there */
+ virBufferAddLit(&histogramChildBuf, "<bin start='0'/>\n");
+
+ for (; *bins > 0; bins++)
+ virBufferAsprintf(&histogramChildBuf, "<bin start='%u'/>\n", *bins);
+
+ virXMLFormatElement(buf, "latency-histogram", &histogramAttrBuf, &histogramChildBuf);
+}
+
+
static void
virDomainDiskDefFormatDriver(virBuffer *buf,
virDomainDiskDef *disk)
{
g_auto(virBuffer) attrBuf = VIR_BUFFER_INITIALIZER;
g_auto(virBuffer) childBuf = VIR_BUFFER_INIT_CHILD(buf);
+ g_auto(virBuffer) statisticsChildBuf = VIR_BUFFER_INIT_CHILD(&childBuf);
virBufferEscapeString(&attrBuf, " name='%s'", virDomainDiskGetDriver(disk));
@@ -24038,16 +24156,25 @@ virDomainDiskDefFormatDriver(virBuffer *buf,
virDomainIothreadMappingDefFormat(&childBuf, disk->iothreads);
if (disk->statistics) {
- g_auto(virBuffer) statisticsChildBuf = VIR_BUFFER_INIT_CHILD(&childBuf);
size_t i;
for (i = 0; disk->statistics[i] > 0; i++)
virBufferAsprintf(&statisticsChildBuf, "<statistic interval='%u'/>\n",
disk->statistics[i]);
-
- virXMLFormatElement(&childBuf, "statistics", NULL, &statisticsChildBuf);
}
+ virDomainDiskDefFormatDriverHistogram(&statisticsChildBuf, NULL,
+ disk->histogram_boundaries);
+ virDomainDiskDefFormatDriverHistogram(&statisticsChildBuf, "read",
+ disk->histogram_boundaries_read);
+ virDomainDiskDefFormatDriverHistogram(&statisticsChildBuf, "write",
+ disk->histogram_boundaries_write);
+ virDomainDiskDefFormatDriverHistogram(&statisticsChildBuf, "zone",
+ disk->histogram_boundaries_zone);
+ virDomainDiskDefFormatDriverHistogram(&statisticsChildBuf, "flush",
+ disk->histogram_boundaries_flush);
+
+ virXMLFormatElement(&childBuf, "statistics", NULL, &statisticsChildBuf);
virXMLFormatElement(buf, "driver", &attrBuf, &childBuf);
}
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 8f53ed96c0..b120d4a68e 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -596,6 +596,13 @@ struct _virDomainDiskDef {
GSList *iothreads; /* List of virDomainIothreadMappingDef */
unsigned int *statistics; /* Optional, zero terminated list of intervals to
collect statistics for */
+ /* optional zero terminated lists of bin boundaries for latency histograms */
+ unsigned int *histogram_boundaries;
+ unsigned int *histogram_boundaries_read;
+ unsigned int *histogram_boundaries_write;
+ unsigned int *histogram_boundaries_zone;
+ unsigned int *histogram_boundaries_flush;
+
virDomainDiskDetectZeroes detect_zeroes;
virTristateSwitch discard_no_unref;
char *domain_name; /* backend domain name */
diff --git a/src/conf/schemas/domaincommon.rng b/src/conf/schemas/domaincommon.rng
index 1f9ac102a0..441328a08e 100644
--- a/src/conf/schemas/domaincommon.rng
+++ b/src/conf/schemas/domaincommon.rng
@@ -2728,13 +2728,36 @@
</optional>
<optional>
<element name="statistics">
- <zeroOrMore>
- <element name="statistic">
- <attribute name="interval">
- <ref name="unsignedInt"/>
- </attribute>
- </element>
- </zeroOrMore>
+ <interleave>
+ <zeroOrMore>
+ <element name="statistic">
+ <attribute name="interval">
+ <ref name="unsignedInt"/>
+ </attribute>
+ </element>
+ </zeroOrMore>
+ <zeroOrMore>
+ <element name="latency-histogram">
+ <optional>
+ <attribute name='type'>
+ <choice>
+ <value>read</value>
+ <value>write</value>
+ <value>zone</value>
+ <value>flush</value>
+ </choice>
+ </attribute>
+ </optional>
+ <oneOrMore>
+ <element name='bin'>
+ <attribute name='start'>
+ <ref name="unsignedInt"/>
+ </attribute>
+ </element>
+ </oneOrMore>
+ </element>
+ </zeroOrMore>
+ </interleave>
</element>
</optional>
</interleave>
diff --git a/tests/qemuxmlconfdata/disk-statistics-intervals.x86_64-latest.xml b/tests/qemuxmlconfdata/disk-statistics-intervals.x86_64-latest.xml
index 4c55c50ef5..d02f954073 100644
--- a/tests/qemuxmlconfdata/disk-statistics-intervals.x86_64-latest.xml
+++ b/tests/qemuxmlconfdata/disk-statistics-intervals.x86_64-latest.xml
@@ -22,6 +22,11 @@
<statistics>
<statistic interval='3'/>
<statistic interval='10'/>
+ <latency-histogram>
+ <bin start='0'/>
+ <bin start='20'/>
+ <bin start='30'/>
+ </latency-histogram>
</statistics>
</driver>
<source file='/var/lib/libvirt/images/iothrtest1.img'/>
@@ -33,6 +38,30 @@
<statistics>
<statistic interval='5'/>
<statistic interval='15'/>
+ <latency-histogram type='read'>
+ <bin start='0'/>
+ <bin start='10'/>
+ <bin start='20'/>
+ <bin start='30'/>
+ </latency-histogram>
+ <latency-histogram type='write'>
+ <bin start='0'/>
+ <bin start='10'/>
+ <bin start='20'/>
+ <bin start='30'/>
+ </latency-histogram>
+ <latency-histogram type='zone'>
+ <bin start='0'/>
+ <bin start='10'/>
+ <bin start='20'/>
+ <bin start='30'/>
+ </latency-histogram>
+ <latency-histogram type='flush'>
+ <bin start='0'/>
+ <bin start='10'/>
+ <bin start='20'/>
+ <bin start='30'/>
+ </latency-histogram>
</statistics>
</driver>
<source file='/var/lib/libvirt/images/iothrtest2.img'/>
diff --git a/tests/qemuxmlconfdata/disk-statistics-intervals.xml b/tests/qemuxmlconfdata/disk-statistics-intervals.xml
index f5e801f5a8..5f9e9470d7 100644
--- a/tests/qemuxmlconfdata/disk-statistics-intervals.xml
+++ b/tests/qemuxmlconfdata/disk-statistics-intervals.xml
@@ -19,6 +19,11 @@
<statistics>
<statistic interval='3'/>
<statistic interval='10'/>
+ <latency-histogram>
+ <bin start='0'/>
+ <bin start='20'/>
+ <bin start='30'/>
+ </latency-histogram>
</statistics>
</driver>
<source file='/var/lib/libvirt/images/iothrtest1.img'/>
@@ -29,6 +34,26 @@
<statistics>
<statistic interval='5'/>
<statistic interval='15'/>
+ <latency-histogram type='read'>
+ <bin start='10'/>
+ <bin start='20'/>
+ <bin start='30'/>
+ </latency-histogram>
+ <latency-histogram type='write'>
+ <bin start='10'/>
+ <bin start='20'/>
+ <bin start='30'/>
+ </latency-histogram>
+ <latency-histogram type='zone'>
+ <bin start='10'/>
+ <bin start='20'/>
+ <bin start='30'/>
+ </latency-histogram>
+ <latency-histogram type='flush'>
+ <bin start='10'/>
+ <bin start='20'/>
+ <bin start='30'/>
+ </latency-histogram>
</statistics>
</driver>
<source file='/var/lib/libvirt/images/iothrtest2.img'/>
--
2.53.0

View File

@ -0,0 +1,125 @@
From c2eb6d70891d9be5ce13f07946841239a81c3ed9 Mon Sep 17 00:00:00 2001
Message-ID: <c2eb6d70891d9be5ce13f07946841239a81c3ed9.1771336681.git.jdenemar@redhat.com>
From: Peter Krempa <pkrempa@redhat.com>
Date: Mon, 16 Feb 2026 15:08:54 +0100
Subject: [PATCH] RHEL-ONLY: backport test data for 'migrate-pr' capability of
'scsi-block'
In upstream qemu the capability is present starting with qemu-11.0. We
don't have the test data downstream and backporting them would be too
invasive. Backport the relevant capability detection as a
downstream-only fix.
https://issues.redhat.com/browse/RHEL-140614 [rhel-9.8]
https://issues.redhat.com/browse/RHEL-135115 [rhel-10.2]
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
---
.../caps_10.2.0_x86_64.replies | 79 ++++++++++++++++++-
.../caps_10.2.0_x86_64.xml | 1 +
2 files changed, 76 insertions(+), 4 deletions(-)
diff --git a/tests/qemucapabilitiesdata/caps_10.2.0_x86_64.replies b/tests/qemucapabilitiesdata/caps_10.2.0_x86_64.replies
index cb4abb4533..10db9baca1 100644
--- a/tests/qemucapabilitiesdata/caps_10.2.0_x86_64.replies
+++ b/tests/qemucapabilitiesdata/caps_10.2.0_x86_64.replies
@@ -33081,10 +33081,81 @@
}
{
- "error": {
- "class": "DeviceNotFound",
- "desc": "The libvirt device dump was not collected for this version+device tuple"
- },
+ "return": [
+ {
+ "default-value": 4294967295,
+ "name": "scsi-id",
+ "type": "uint32"
+ },
+ {
+ "default-value": 4294967295,
+ "name": "lun",
+ "type": "uint32"
+ },
+ {
+ "default-value": 0,
+ "name": "channel",
+ "type": "uint32"
+ },
+ {
+ "default-value": "auto",
+ "name": "rerror",
+ "description": "Error handling policy (report/ignore/enospc/stop/auto)",
+ "type": "BlockdevOnError"
+ },
+ {
+ "default-value": 2147483647,
+ "name": "max_io_size",
+ "type": "uint64"
+ },
+ {
+ "default-value": false,
+ "name": "share-rw",
+ "description": "on/off",
+ "type": "bool"
+ },
+ {
+ "default-value": true,
+ "name": "migrate-pr",
+ "description": "on/off",
+ "type": "bool"
+ },
+ {
+ "default-value": "auto",
+ "name": "werror",
+ "description": "Error handling policy (report/ignore/enospc/stop/auto)",
+ "type": "BlockdevOnError"
+ },
+ {
+ "default-value": 1073741824,
+ "name": "max_unmap_size",
+ "type": "uint64"
+ },
+ {
+ "default-value": -1,
+ "name": "scsi_version",
+ "type": "int32"
+ },
+ {
+ "default-value": 0,
+ "name": "rotation_rate",
+ "type": "uint16"
+ },
+ {
+ "name": "drive",
+ "description": "Node name or ID of a block device to use as a backend",
+ "type": "str"
+ },
+ {
+ "default-value": 30,
+ "name": "io_timeout",
+ "type": "uint32"
+ },
+ {
+ "name": "bootindex",
+ "type": "int32"
+ }
+ ],
"id": "libvirt-37"
}
diff --git a/tests/qemucapabilitiesdata/caps_10.2.0_x86_64.xml b/tests/qemucapabilitiesdata/caps_10.2.0_x86_64.xml
index 7cff2c2291..7d5a75ce88 100644
--- a/tests/qemucapabilitiesdata/caps_10.2.0_x86_64.xml
+++ b/tests/qemucapabilitiesdata/caps_10.2.0_x86_64.xml
@@ -215,6 +215,7 @@
<flag name='acpi-generic-initiator'/>
<flag name='disk-timed-stats'/>
<flag name='query-accelerators'/>
+ <flag name='scsi-block.migrate-pr'/>
<version>10001091</version>
<microcodeVersion>43100287</microcodeVersion>
<package>v10.2.0-rc1-38-gfb241d0a1f</package>
--
2.53.0

View File

@ -0,0 +1,85 @@
From 271cfe0d7954d5398af307b24fc5b601977975b8 Mon Sep 17 00:00:00 2001
Message-ID: <271cfe0d7954d5398af307b24fc5b601977975b8.1772815313.git.jdenemar@redhat.com>
From: Andrea Bolognani <abologna@redhat.com>
Date: Mon, 9 Feb 2026 21:28:50 +0100
Subject: [PATCH] conf: Add firmwareFeatures element for domaincaps
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit 928bdc3e67b29ff2314ff538905703e299b1e47e)
https://issues.redhat.com/browse/RHEL-82645
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
---
src/conf/domain_capabilities.c | 15 +++++++++++++++
src/conf/domain_capabilities.h | 8 ++++++++
2 files changed, 23 insertions(+)
diff --git a/src/conf/domain_capabilities.c b/src/conf/domain_capabilities.c
index 49179b97ab..9b3577cd08 100644
--- a/src/conf/domain_capabilities.c
+++ b/src/conf/domain_capabilities.c
@@ -422,6 +422,19 @@ virDomainCapsFeatureFormatSimple(virBuffer *buf,
}
+static void
+virDomainCapsFirmwareFeaturesFormat(virBuffer *buf,
+ const virDomainCapsFirmwareFeatures *firmwareFeatures)
+{
+ FORMAT_PROLOGUE(firmwareFeatures);
+
+ ENUM_PROCESS(firmwareFeatures, secureBoot, virTristateBoolTypeToString);
+ ENUM_PROCESS(firmwareFeatures, enrolledKeys, virTristateBoolTypeToString);
+
+ FORMAT_EPILOGUE(firmwareFeatures);
+}
+
+
static void
virDomainCapsLoaderFormat(virBuffer *buf,
const virDomainCapsLoader *loader)
@@ -440,12 +453,14 @@ static void
virDomainCapsOSFormat(virBuffer *buf,
const virDomainCapsOS *os)
{
+ const virDomainCapsFirmwareFeatures *firmwareFeatures = &os->firmwareFeatures;
const virDomainCapsLoader *loader = &os->loader;
FORMAT_PROLOGUE(os);
ENUM_PROCESS(os, firmware, virDomainOsDefFirmwareTypeToString);
+ virDomainCapsFirmwareFeaturesFormat(&childBuf, firmwareFeatures);
virDomainCapsLoaderFormat(&childBuf, loader);
FORMAT_EPILOGUE(os);
diff --git a/src/conf/domain_capabilities.h b/src/conf/domain_capabilities.h
index b10370db8f..a68fafe235 100644
--- a/src/conf/domain_capabilities.h
+++ b/src/conf/domain_capabilities.h
@@ -43,6 +43,13 @@ struct _virDomainCapsStringValues {
size_t nvalues; /* number of strings */
};
+typedef struct _virDomainCapsFirmwareFeatures virDomainCapsFirmwareFeatures;
+struct _virDomainCapsFirmwareFeatures {
+ virTristateBool supported;
+ virDomainCapsEnum secureBoot;
+ virDomainCapsEnum enrolledKeys;
+};
+
STATIC_ASSERT_ENUM(VIR_DOMAIN_LOADER_TYPE_LAST);
STATIC_ASSERT_ENUM(VIR_TRISTATE_BOOL_LAST);
typedef struct _virDomainCapsLoader virDomainCapsLoader;
@@ -59,6 +66,7 @@ typedef struct _virDomainCapsOS virDomainCapsOS;
struct _virDomainCapsOS {
virTristateBool supported;
virDomainCapsEnum firmware; /* Info about virDomainOsDefFirmware */
+ virDomainCapsFirmwareFeatures firmwareFeatures;
virDomainCapsLoader loader; /* Info about virDomainLoaderDef */
};
--
2.53.0

View File

@ -0,0 +1,140 @@
From af94300604718604a70a5d587e56187ffe5e6557 Mon Sep 17 00:00:00 2001
Message-ID: <af94300604718604a70a5d587e56187ffe5e6557.1772815313.git.jdenemar@redhat.com>
From: Andrea Bolognani <abologna@redhat.com>
Date: Fri, 30 Jan 2026 17:46:30 +0100
Subject: [PATCH] conf: Include varstore element in domcaps
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
We want to advertise whether the element is usable when
defining new domains.
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
(cherry picked from commit 3d6987914bb10beb11b9eb5e83ec2194dfab1659)
https://issues.redhat.com/browse/RHEL-82645
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
---
docs/formatdomaincaps.rst | 7 +++++++
src/conf/domain_capabilities.c | 10 ++++++++++
src/conf/domain_capabilities.h | 6 ++++++
src/conf/schemas/domaincaps.rng | 9 +++++++++
4 files changed, 32 insertions(+)
diff --git a/docs/formatdomaincaps.rst b/docs/formatdomaincaps.rst
index 3426b7c9cd..5a1d3f2670 100644
--- a/docs/formatdomaincaps.rst
+++ b/docs/formatdomaincaps.rst
@@ -141,6 +141,7 @@ domains.
<value>no</value>
</enum>
</loader>
+ <varstore supported='yes'/>
</os>
...
<domainCapabilities>
@@ -227,6 +228,12 @@ are the following:
possible to enforce Secure Boot, look at the ``enrolledKeys`` enum inside
the ``<firmwareFeatures/>`` element instead.
+The ``<varstore/>`` element :since:`(since 12.1.0)` indicates whether UEFI
+variable storage backed by the ``uefi-vars`` QEMU device can be used as an
+alternative to pflash-based NVRAM storage. This is the only type of variable
+storage compatible with Secure Boot on non-x86 architectures, but it can be
+used on x86 too.
+
CPU configuration
~~~~~~~~~~~~~~~~~
diff --git a/src/conf/domain_capabilities.c b/src/conf/domain_capabilities.c
index 9b3577cd08..78b8e6e6e1 100644
--- a/src/conf/domain_capabilities.c
+++ b/src/conf/domain_capabilities.c
@@ -449,12 +449,21 @@ virDomainCapsLoaderFormat(virBuffer *buf,
FORMAT_EPILOGUE(loader);
}
+static void
+virDomainCapsVarstoreFormat(virBuffer *buf,
+ const virDomainCapsVarstore *varstore)
+{
+ FORMAT_PROLOGUE(varstore);
+ FORMAT_EPILOGUE(varstore);
+}
+
static void
virDomainCapsOSFormat(virBuffer *buf,
const virDomainCapsOS *os)
{
const virDomainCapsFirmwareFeatures *firmwareFeatures = &os->firmwareFeatures;
const virDomainCapsLoader *loader = &os->loader;
+ const virDomainCapsVarstore *varstore = &os->varstore;
FORMAT_PROLOGUE(os);
@@ -462,6 +471,7 @@ virDomainCapsOSFormat(virBuffer *buf,
virDomainCapsFirmwareFeaturesFormat(&childBuf, firmwareFeatures);
virDomainCapsLoaderFormat(&childBuf, loader);
+ virDomainCapsVarstoreFormat(&childBuf, varstore);
FORMAT_EPILOGUE(os);
}
diff --git a/src/conf/domain_capabilities.h b/src/conf/domain_capabilities.h
index a68fafe235..02344fd9b6 100644
--- a/src/conf/domain_capabilities.h
+++ b/src/conf/domain_capabilities.h
@@ -61,6 +61,11 @@ struct _virDomainCapsLoader {
virDomainCapsEnum secure; /* Info about secure:virTristateBool */
};
+typedef struct _virDomainCapsVarstore virDomainCapsVarstore;
+struct _virDomainCapsVarstore {
+ virTristateBool supported;
+};
+
STATIC_ASSERT_ENUM(VIR_DOMAIN_OS_DEF_FIRMWARE_LAST);
typedef struct _virDomainCapsOS virDomainCapsOS;
struct _virDomainCapsOS {
@@ -68,6 +73,7 @@ struct _virDomainCapsOS {
virDomainCapsEnum firmware; /* Info about virDomainOsDefFirmware */
virDomainCapsFirmwareFeatures firmwareFeatures;
virDomainCapsLoader loader; /* Info about virDomainLoaderDef */
+ virDomainCapsVarstore varstore;
};
STATIC_ASSERT_ENUM(VIR_DOMAIN_MEMORY_SOURCE_LAST);
diff --git a/src/conf/schemas/domaincaps.rng b/src/conf/schemas/domaincaps.rng
index 3b24caeca6..4682abbf41 100644
--- a/src/conf/schemas/domaincaps.rng
+++ b/src/conf/schemas/domaincaps.rng
@@ -87,6 +87,12 @@
</element>
</define>
+ <define name="varstore">
+ <element name="varstore">
+ <ref name="supported"/>
+ </element>
+ </define>
+
<define name="os">
<element name="os">
<interleave>
@@ -98,6 +104,9 @@
<optional>
<ref name="loader"/>
</optional>
+ <optional>
+ <ref name="varstore"/>
+ </optional>
</interleave>
</element>
</define>
--
2.53.0

View File

@ -0,0 +1,69 @@
From c0fbd0d516a2c4457789d158bfdea839255d0854 Mon Sep 17 00:00:00 2001
Message-ID: <c0fbd0d516a2c4457789d158bfdea839255d0854.1771423659.git.jdenemar@redhat.com>
From: Pavel Hrdina <phrdina@redhat.com>
Date: Sat, 14 Feb 2026 06:14:20 +0100
Subject: [PATCH] conf: Introduce iommufd enum for domaincaps
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit 855f8fe9e2454555ba84696750e0e1501dd5ba80)
Resolves: https://issues.redhat.com/browse/RHEL-148135
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
---
docs/formatdomaincaps.rst | 7 +++++++
src/conf/domain_capabilities.c | 1 +
src/conf/domain_capabilities.h | 1 +
3 files changed, 9 insertions(+)
diff --git a/docs/formatdomaincaps.rst b/docs/formatdomaincaps.rst
index 8b4f0ecff3..6ba7f84f96 100644
--- a/docs/formatdomaincaps.rst
+++ b/docs/formatdomaincaps.rst
@@ -461,6 +461,10 @@ Well, only if the following is enabled:
<value>vfio</value>
<value>xen</value>
</enum>
+ <enum name='iommufd'>
+ <value>yes</value>
+ <value>no</value>
+ </enum>
</hostdev>
</devices>
</domainCapabilities>
@@ -477,6 +481,9 @@ Well, only if the following is enabled:
``mode="capabilities"``.
``pciBackend``
Options for the ``name`` attribute of the <driver/> element.
+``iommufd``
+ Options for the ``iommufd`` attribute of the <driver/> element.
+ :since:`Since 12.1.0`
RNG device
^^^^^^^^^^
diff --git a/src/conf/domain_capabilities.c b/src/conf/domain_capabilities.c
index f843124695..49179b97ab 100644
--- a/src/conf/domain_capabilities.c
+++ b/src/conf/domain_capabilities.c
@@ -620,6 +620,7 @@ virDomainCapsDeviceHostdevFormat(virBuffer *buf,
ENUM_PROCESS(hostdev, subsysType, virDomainHostdevSubsysTypeToString);
ENUM_PROCESS(hostdev, capsType, virDomainHostdevCapsTypeToString);
ENUM_PROCESS(hostdev, pciBackend, virDeviceHostdevPCIDriverNameTypeToString);
+ ENUM_PROCESS(hostdev, iommufd, virTristateBoolTypeToString);
FORMAT_EPILOGUE(hostdev);
}
diff --git a/src/conf/domain_capabilities.h b/src/conf/domain_capabilities.h
index 437981c711..b10370db8f 100644
--- a/src/conf/domain_capabilities.h
+++ b/src/conf/domain_capabilities.h
@@ -108,6 +108,7 @@ struct _virDomainCapsDeviceHostdev {
virDomainCapsEnum subsysType; /* Info about virDomainHostdevSubsysType */
virDomainCapsEnum capsType; /* Info about virDomainHostdevCapsType */
virDomainCapsEnum pciBackend; /* Info about virDomainHostdevSubsysPCIBackendType */
+ virDomainCapsEnum iommufd; /* Info about iommufd:virTristateBool */
/* add new fields here */
};
--
2.53.0

View File

@ -0,0 +1,132 @@
From 4e8fe2eb42b47a55e491a63e2600a24e0501fd1f Mon Sep 17 00:00:00 2001
Message-ID: <4e8fe2eb42b47a55e491a63e2600a24e0501fd1f.1771423658.git.jdenemar@redhat.com>
From: Pavel Hrdina <phrdina@redhat.com>
Date: Sun, 15 Feb 2026 18:19:56 +0100
Subject: [PATCH] conf: Introduce virDomainDefHasPCIHostdevWithIOMMUFD
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit 4b176cfc3877cca882d63ab4ed446794d7a05722)
Resolves: https://issues.redhat.com/browse/RHEL-150351
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
---
src/conf/domain_conf.c | 14 ++++++++++++++
src/conf/domain_conf.h | 3 +++
src/libvirt_private.syms | 1 +
src/qemu/qemu_command.c | 42 ++++++++++++----------------------------
4 files changed, 30 insertions(+), 30 deletions(-)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 9ae48e9abc..cb047e5a3e 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -32482,6 +32482,20 @@ virDomainDefHasPCIHostdev(const virDomainDef *def)
}
+bool
+virDomainDefHasPCIHostdevWithIOMMUFD(const virDomainDef *def)
+{
+ size_t i;
+
+ for (i = 0; i < def->nhostdevs; i++) {
+ if (virHostdevIsPCIDeviceWithIOMMUFD(def->hostdevs[i]))
+ return true;
+ }
+
+ return false;
+}
+
+
bool
virDomainDefHasMdevHostdev(const virDomainDef *def)
{
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index d958ed04f9..69a8e79c6d 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -4655,6 +4655,9 @@ virDomainDefHasNVMeDisk(const virDomainDef *def);
bool
virDomainDefHasPCIHostdev(const virDomainDef *def);
+bool
+virDomainDefHasPCIHostdevWithIOMMUFD(const virDomainDef *def);
+
bool
virDomainDefHasMdevHostdev(const virDomainDef *def);
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 863e50ec4f..effe44fe57 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -348,6 +348,7 @@ virDomainDefHasNVMeDisk;
virDomainDefHasOldStyleROUEFI;
virDomainDefHasOldStyleUEFI;
virDomainDefHasPCIHostdev;
+virDomainDefHasPCIHostdevWithIOMMUFD;
virDomainDefHasTimer;
virDomainDefHasUSB;
virDomainDefHasVcpusOffline;
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index c8626e6d49..3119191413 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -5349,43 +5349,25 @@ qemuBuildIOMMUFDCommandLine(virCommand *cmd,
const virDomainDef *def,
virDomainObj *vm)
{
- size_t i;
qemuDomainObjPrivate *priv = vm->privateData;
g_autofree char *fdstr = g_strdup_printf("%d", priv->iommufd);
+ g_autoptr(virJSONValue) props = NULL;
+ if (!virDomainDefHasPCIHostdevWithIOMMUFD(def))
+ return 0;
- for (i = 0; i < def->nhostdevs; i++) {
- virDomainHostdevDef *hostdev = def->hostdevs[i];
- virDomainHostdevSubsys *subsys = &hostdev->source.subsys;
- g_autoptr(virJSONValue) props = NULL;
+ virCommandPassFD(cmd, priv->iommufd, VIR_COMMAND_PASS_FD_CLOSE_PARENT);
- if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
- continue;
+ priv->iommufd = -1;
- if (subsys->type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
- continue;
+ if (qemuMonitorCreateObjectProps(&props, "iommufd",
+ "iommufd0",
+ "S:fd", fdstr,
+ NULL) < 0)
+ return -1;
- if (hostdev->info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_UNASSIGNED)
- continue;
-
- if (subsys->u.pci.driver.iommufd != VIR_TRISTATE_BOOL_YES)
- continue;
-
- virCommandPassFD(cmd, priv->iommufd, VIR_COMMAND_PASS_FD_CLOSE_PARENT);
-
- priv->iommufd = -1;
-
- if (qemuMonitorCreateObjectProps(&props, "iommufd",
- "iommufd0",
- "S:fd", fdstr,
- NULL) < 0)
- return -1;
-
- if (qemuBuildObjectCommandlineFromJSON(cmd, props) < 0)
- return -1;
-
- break;
- }
+ if (qemuBuildObjectCommandlineFromJSON(cmd, props) < 0)
+ return -1;
return 0;
}
--
2.53.0

View File

@ -0,0 +1,89 @@
From 615f11792c8988cfd6a30717dcc8d5d9174ea508 Mon Sep 17 00:00:00 2001
Message-ID: <615f11792c8988cfd6a30717dcc8d5d9174ea508.1771423658.git.jdenemar@redhat.com>
From: Pavel Hrdina <phrdina@redhat.com>
Date: Sun, 15 Feb 2026 18:19:23 +0100
Subject: [PATCH] conf: Introduce virHostdevIsPCIDeviceWithIOMMUFD
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit 97eed30948e980be8b7552fff637e828768854e4)
Resolves: https://issues.redhat.com/browse/RHEL-150351
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
---
src/conf/domain_conf.c | 15 +++++++++++++++
src/conf/domain_conf.h | 3 +++
src/libvirt_private.syms | 1 +
src/qemu/qemu_process.c | 5 +----
4 files changed, 20 insertions(+), 4 deletions(-)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 83c58ab5ff..9ae48e9abc 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -32758,6 +32758,21 @@ virHostdevIsPCIDevice(const virDomainHostdevDef *hostdev)
}
+/**
+ * virHostdevIsPCIDeviceWithIOMMUFD:
+ * @hostdev: host device to check
+ *
+ * Returns true if @hostdev is a PCI device with IOMMUFD enabled, false otherwise.
+ */
+bool
+virHostdevIsPCIDeviceWithIOMMUFD(const virDomainHostdevDef *hostdev)
+{
+ return virHostdevIsPCIDevice(hostdev) &&
+ hostdev->source.subsys.u.pci.driver.name == VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_VFIO &&
+ hostdev->source.subsys.u.pci.driver.iommufd == VIR_TRISTATE_BOOL_YES;
+}
+
+
static void
virDomainObjGetMessagesIOErrorsSrc(virStorageSource *src,
const char *diskdst,
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index b120d4a68e..d958ed04f9 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -4713,6 +4713,9 @@ virHostdevIsMdevDevice(const virDomainHostdevDef *hostdev)
bool
virHostdevIsPCIDevice(const virDomainHostdevDef *hostdev)
ATTRIBUTE_NONNULL(1);
+bool
+virHostdevIsPCIDeviceWithIOMMUFD(const virDomainHostdevDef *hostdev)
+ ATTRIBUTE_NONNULL(1);
void
virDomainObjGetMessagesIOErrorsChain(virStorageSource *src,
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 9ae44e31b8..863e50ec4f 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -812,6 +812,7 @@ virDomainQemuMonitorEventNew;
virDomainQemuMonitorEventStateRegisterID;
virHostdevIsMdevDevice;
virHostdevIsPCIDevice;
+virHostdevIsPCIDeviceWithIOMMUFD;
virHostdevIsSCSIDevice;
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 7e32325fa0..3bd81c55b3 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -7732,10 +7732,7 @@ qemuProcessOpenVfioFds(virDomainObj *vm)
for (i = 0; i < vm->def->nhostdevs; i++) {
virDomainHostdevDef *hostdev = vm->def->hostdevs[i];
- if (hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
- hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI &&
- hostdev->source.subsys.u.pci.driver.name == VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_VFIO &&
- hostdev->source.subsys.u.pci.driver.iommufd == VIR_TRISTATE_BOOL_YES) {
+ if (virHostdevIsPCIDeviceWithIOMMUFD(hostdev)) {
/* Open VFIO device FD */
if (qemuProcessOpenVfioDeviceFd(hostdev) < 0)
return -1;
--
2.53.0

View File

@ -0,0 +1,104 @@
From 08ff36546b810ae14135c19c99fb1dc1aa5fcbb2 Mon Sep 17 00:00:00 2001
Message-ID: <08ff36546b810ae14135c19c99fb1dc1aa5fcbb2.1772815313.git.jdenemar@redhat.com>
From: Andrea Bolognani <abologna@redhat.com>
Date: Tue, 3 Feb 2026 15:18:39 +0100
Subject: [PATCH] conf: Move type=rom default for loader to drivers
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Right now we set this default in the common parsing code, which
is not a big problem per se but would get in the way of some
upcoming changes.
Leave this choice to individual drivers instead. Only the QEMU
and Xen drivers use the value for anything, so we can limit the
amount of code duplication this change causes.
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
(cherry picked from commit 1504b7f687bdfc679377e605d076776b18533468)
https://issues.redhat.com/browse/RHEL-82645
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
---
src/conf/domain_postparse.c | 19 -------------------
src/libxl/libxl_domain.c | 6 ++++++
src/qemu/qemu_firmware.c | 5 +++++
3 files changed, 11 insertions(+), 19 deletions(-)
diff --git a/src/conf/domain_postparse.c b/src/conf/domain_postparse.c
index 38e731348d..cbaae75c02 100644
--- a/src/conf/domain_postparse.c
+++ b/src/conf/domain_postparse.c
@@ -89,22 +89,6 @@ virDomainDefPostParseMemory(virDomainDef *def,
}
-static int
-virDomainDefPostParseOs(virDomainDef *def)
-{
- if (!def->os.loader)
- return 0;
-
- if (def->os.loader->path &&
- def->os.loader->type == VIR_DOMAIN_LOADER_TYPE_NONE) {
- /* By default, loader is type of 'rom' */
- def->os.loader->type = VIR_DOMAIN_LOADER_TYPE_ROM;
- }
-
- return 0;
-}
-
-
static void
virDomainDefPostParseMemtune(virDomainDef *def)
{
@@ -1251,9 +1235,6 @@ virDomainDefPostParseCommon(virDomainDef *def,
if (virDomainDefPostParseMemory(def, data->parseFlags) < 0)
return -1;
- if (virDomainDefPostParseOs(def) < 0)
- return -1;
-
virDomainDefPostParseMemtune(def);
if (virDomainDefRejectDuplicateControllers(def) < 0)
diff --git a/src/libxl/libxl_domain.c b/src/libxl/libxl_domain.c
index 9842d6fece..c6717e31cf 100644
--- a/src/libxl/libxl_domain.c
+++ b/src/libxl/libxl_domain.c
@@ -279,6 +279,12 @@ libxlDomainDefPostParse(virDomainDef *def,
def->features[VIR_DOMAIN_FEATURE_ACPI] = VIR_TRISTATE_SWITCH_ON;
}
+ if (def->os.loader &&
+ def->os.loader->path &&
+ !def->os.loader->type) {
+ def->os.loader->type = VIR_DOMAIN_LOADER_TYPE_ROM;
+ }
+
/* add implicit balloon device */
if (def->memballoon == NULL) {
virDomainMemballoonDef *memballoon;
diff --git a/src/qemu/qemu_firmware.c b/src/qemu/qemu_firmware.c
index 519828f6f9..6a074055ca 100644
--- a/src/qemu/qemu_firmware.c
+++ b/src/qemu/qemu_firmware.c
@@ -1662,6 +1662,11 @@ qemuFirmwareFillDomainCustom(virDomainDef *def)
if (!loader)
return;
+ if (loader->path &&
+ !loader->type) {
+ loader->type = VIR_DOMAIN_LOADER_TYPE_ROM;
+ }
+
if (loader->path &&
!loader->format) {
loader->format = VIR_STORAGE_FILE_RAW;
--
2.53.0

View File

@ -0,0 +1,385 @@
From 50a7a37ea4d6c8ffab8110a58db1b16b9d1d7b84 Mon Sep 17 00:00:00 2001
Message-ID: <50a7a37ea4d6c8ffab8110a58db1b16b9d1d7b84.1772815313.git.jdenemar@redhat.com>
From: Andrea Bolognani <abologna@redhat.com>
Date: Mon, 19 Jan 2026 14:20:06 +0100
Subject: [PATCH] conf: Parse and format varstore element
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This will be used to configure the backing storage used by the
uefi-vars QEMU device.
Dealing with the element itself is trivial, however we have to
refactor the existing code which deals with the loader and nvram
elements slightly: in particular, we can no longer perform an
early exit if those elements are absent.
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
(cherry picked from commit 3feee6d0aba5abf5e69d69b0022c08ea6bd5af3e)
https://issues.redhat.com/browse/RHEL-82645
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
---
docs/formatdomain.rst | 23 +++++++--
docs/kbase/secureboot.rst | 46 ++++++++++++------
src/conf/domain_conf.c | 81 ++++++++++++++++++++++++++++---
src/conf/domain_conf.h | 9 ++++
src/conf/schemas/domaincommon.rng | 22 ++++++++-
src/conf/virconftypes.h | 2 +
src/libvirt_private.syms | 2 +
7 files changed, 157 insertions(+), 28 deletions(-)
diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst
index 152fd7f530..7d6cc45efd 100644
--- a/docs/formatdomain.rst
+++ b/docs/formatdomain.rst
@@ -196,9 +196,9 @@ harddisk, cdrom, network) determining where to obtain/find the boot image.
``firmware``
The ``firmware`` attribute allows management applications to automatically
- fill ``<loader/>`` and ``<nvram/>`` elements and possibly enable some
- features required by selected firmware. Accepted values are ``bios`` and
- ``efi``.
+ fill ``<loader/>`` and ``<nvram/>`` or ``<varstore/>`` elements and possibly
+ enable some features required by selected firmware. Accepted values are
+ ``bios`` and ``efi``.
The selection process scans for files describing installed firmware images in
specified location and uses the most specific one which fulfills domain
requirements. The locations in order of preference (from generic to most
@@ -311,6 +311,23 @@ harddisk, cdrom, network) determining where to obtain/find the boot image.
It is not valid to provide this element if the loader is marked as
stateless.
+``varstore``
+ This works much the same way as the ``<nvram/>`` element described above,
+ except that variable storage is handled by the ``uefi-vars`` QEMU device
+ instead of being backed by a pflash device. :since:`Since 12.1.0 (QEMU only)`
+
+ The ``path`` attribute contains the path of the domain-specific file where
+ variables are stored, while the ``template`` attribute points to a template
+ that the domain-specific file can be (re)generated from. Assuming that the
+ necessary JSON firmware descriptor files are present, both attributes will
+ be filled in automatically by libvirt.
+
+ Using ``<varstore/>`` instead of ``<nvram/>`` is particularly useful on
+ non-x86 architectures such as aarch64, where it represents the only way to
+ get Secure Boot working. It can be used on x86 too, and doing so will make
+ it possible to keep UEFI authenticated variables safe from tampering without
+ requiring the use of SMM emulation.
+
``boot``
The ``dev`` attribute takes one of the values "fd", "hd", "cdrom" or
"network" and is used to specify the next boot device to consider. The
diff --git a/docs/kbase/secureboot.rst b/docs/kbase/secureboot.rst
index 6c22b08d22..b411b65f00 100644
--- a/docs/kbase/secureboot.rst
+++ b/docs/kbase/secureboot.rst
@@ -74,8 +74,8 @@ Changing an existing VM
When a VM is defined, libvirt will pick the firmware that best
satisfies the provided criteria and record this information for use
-on subsequent boots. The resulting XML configuration will look like
-this:
+on subsequent boots. The resulting XML configuration will look either
+like this:
::
@@ -88,14 +88,28 @@ this:
<nvram template='/usr/share/edk2/ovmf/OVMF_VARS.secboot.fd'>/var/lib/libvirt/qemu/nvram/vm_VARS.fd</nvram>
</os>
+or like this:
+
+::
+
+ <os firmware='efi'>
+ <firmware>
+ <feature enabled='yes' name='enrolled-keys'/>
+ <feature enabled='yes' name='secure-boot'/>
+ </firmware>
+ <loader type='rom' format='raw'>/usr/share/edk2/aarch64/QEMU_EFI.qemuvars.fd</loader>
+ <varstore template='/usr/share/edk2/aarch64/vars.secboot.json' path='/var/lib/libvirt/qemu/varstore/vm.json'/>
+ </os>
+
In order to force libvirt to repeat the firmware autoselection
-process, it's necessary to remove the ``<loader>`` and ``<nvram>``
-elements. Failure to do so will likely result in an error.
+process, it's necessary to remove the ``<loader>`` as well as the
+``<nvram>`` or ``<varstore>`` elements, depending on what's
+applicable. Failure to do so will likely result in an error.
Note that updating the XML configuration as described above is
-**not** enough to change the Secure Boot status: the NVRAM file
-associated with the VM has to be regenerated from its template as
-well.
+**not** enough to change the Secure Boot status: the NVRAM/varstore
+file associated with the VM has to be regenerated from its template
+as well.
In order to do that, update the XML and then start the VM with
@@ -107,9 +121,9 @@ This option is only available starting with libvirt 8.1.0, so if your
version of libvirt is older than that you will have to delete the
NVRAM file manually before starting the VM.
-Most guest operating systems will be able to cope with the NVRAM file
-being reinitialized, but in some cases the VM will be unable to boot
-after the change.
+Most guest operating systems will be able to cope with the
+NVRAM/varstore file being reinitialized, but in some cases the VM
+will be unable to boot after the change.
Additional information
@@ -126,15 +140,15 @@ can be used to validate the operating system signature need to be
provided as well.
Asking for the ``enrolled-keys`` firmware feature to be enabled will
-cause libvirt to initialize the NVRAM file associated with the VM
-from a template that contains a suitable set of keys. These keys
-being present will cause the firmware to enforce the Secure Boot
+cause libvirt to initialize the NVRAM/varstore file associated with
+the VM from a template that contains a suitable set of keys. These
+keys being present will cause the firmware to enforce the Secure Boot
signing requirements.
The opposite configuration, where the feature is explicitly disabled,
-will result in no keys being present in the NVRAM file. Unable to
-verify signatures, the firmware will allow even unsigned operating
-systems to run.
+will result in no keys being present in the NVRAM/varstore file.
+Unable to verify signatures, the firmware will allow even unsigned
+operating systems to run.
If running unsigned code is desired, it's also possible to ask for
the ``secure-boot`` feature to be disabled, which will cause libvirt
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index e72cda0048..16ea9f0b2e 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -3932,6 +3932,27 @@ virDomainLoaderDefFree(virDomainLoaderDef *loader)
g_free(loader);
}
+virDomainVarstoreDef *
+virDomainVarstoreDefNew(void)
+{
+ virDomainVarstoreDef *def = NULL;
+
+ def = g_new0(virDomainVarstoreDef, 1);
+
+ return def;
+}
+
+void
+virDomainVarstoreDefFree(virDomainVarstoreDef *varstore)
+{
+ if (!varstore)
+ return;
+
+ g_free(varstore->path);
+ g_free(varstore->template);
+ g_free(varstore);
+}
+
static void
virDomainResctrlMonDefFree(virDomainResctrlMonDef *domresmon)
@@ -4034,6 +4055,7 @@ virDomainOSDefClear(virDomainOSDef *os)
virDomainOSACPITableDefFree(os->acpiTables[i]);
g_free(os->acpiTables);
virDomainLoaderDefFree(os->loader);
+ virDomainVarstoreDefFree(os->varstore);
g_free(os->bootloader);
g_free(os->bootloaderArgs);
}
@@ -17983,6 +18005,17 @@ virDomainLoaderDefParseXMLLoader(virDomainLoaderDef *loader,
}
+static int
+virDomainVarstoreDefParseXML(virDomainVarstoreDef *varstore,
+ xmlNodePtr varstoreNode)
+{
+ varstore->path = virXMLPropString(varstoreNode, "path");
+ varstore->template = virXMLPropString(varstoreNode, "template");
+
+ return 0;
+}
+
+
static int
virDomainLoaderDefParseXML(virDomainLoaderDef *loader,
xmlNodePtr loaderNode,
@@ -18430,16 +18463,29 @@ virDomainDefParseBootLoaderOptions(virDomainDef *def,
xmlNodePtr loaderNode = virXPathNode("./os/loader[1]", ctxt);
xmlNodePtr nvramNode = virXPathNode("./os/nvram[1]", ctxt);
xmlNodePtr nvramSourceNode = virXPathNode("./os/nvram/source[1]", ctxt);
+ xmlNodePtr varstoreNode = virXPathNode("./os/varstore[1]", ctxt);
- if (!loaderNode && !nvramNode)
- return 0;
-
- def->os.loader = virDomainLoaderDefNew();
-
- if (virDomainLoaderDefParseXML(def->os.loader,
- loaderNode, nvramNode, nvramSourceNode,
- ctxt, xmlopt, flags) < 0)
+ if (nvramNode && varstoreNode) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("Cannot have both <nvram> and <varstore>"));
return -1;
+ }
+
+ if (loaderNode || nvramNode) {
+ def->os.loader = virDomainLoaderDefNew();
+
+ if (virDomainLoaderDefParseXML(def->os.loader,
+ loaderNode, nvramNode, nvramSourceNode,
+ ctxt, xmlopt, flags) < 0)
+ return -1;
+ }
+
+ if (varstoreNode) {
+ def->os.varstore = virDomainVarstoreDefNew();
+
+ if (virDomainVarstoreDefParseXML(def->os.varstore, varstoreNode) < 0)
+ return -1;
+ }
return 0;
}
@@ -28062,6 +28108,20 @@ virDomainLoaderDefFormat(virBuffer *buf,
return 0;
}
+static int
+virDomainVarstoreDefFormat(virBuffer *buf,
+ virDomainVarstoreDef *varstore)
+{
+ g_auto(virBuffer) attrBuf = VIR_BUFFER_INITIALIZER;
+
+ virBufferEscapeString(&attrBuf, " template='%s'", varstore->template);
+ virBufferEscapeString(&attrBuf, " path='%s'", varstore->path);
+
+ virXMLFormatElementEmpty(buf, "varstore", &attrBuf, NULL);
+
+ return 0;
+}
+
static void
virDomainKeyWrapDefFormat(virBuffer *buf, virDomainKeyWrapDef *keywrap)
{
@@ -29523,6 +29583,11 @@ virDomainDefFormatInternalSetRootName(virDomainDef *def,
if (def->os.loader &&
virDomainLoaderDefFormat(buf, def->os.loader, xmlopt, flags) < 0)
return -1;
+
+ if (def->os.varstore &&
+ virDomainVarstoreDefFormat(buf, def->os.varstore) < 0)
+ return -1;
+
virBufferEscapeString(buf, "<kernel>%s</kernel>\n",
def->os.kernel);
virBufferEscapeString(buf, "<initrd>%s</initrd>\n",
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 69a8e79c6d..ead3b07475 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -2420,6 +2420,14 @@ struct _virDomainLoaderDef {
virDomainLoaderDef *virDomainLoaderDefNew(void);
void virDomainLoaderDefFree(virDomainLoaderDef *loader);
+struct _virDomainVarstoreDef {
+ char *path;
+ char *template;
+};
+
+virDomainVarstoreDef *virDomainVarstoreDefNew(void);
+void virDomainVarstoreDefFree(virDomainVarstoreDef *varstore);
+
typedef enum {
VIR_DOMAIN_IOAPIC_NONE = 0,
VIR_DOMAIN_IOAPIC_QEMU,
@@ -2573,6 +2581,7 @@ struct _virDomainOSDef {
size_t nacpiTables;
virDomainOSACPITableDef **acpiTables;
virDomainLoaderDef *loader;
+ virDomainVarstoreDef *varstore;
char *bootloader;
char *bootloaderArgs;
int smbios_mode;
diff --git a/src/conf/schemas/domaincommon.rng b/src/conf/schemas/domaincommon.rng
index 92f82c8fbf..7215db3fc1 100644
--- a/src/conf/schemas/domaincommon.rng
+++ b/src/conf/schemas/domaincommon.rng
@@ -349,7 +349,10 @@
</element>
</optional>
<optional>
- <ref name="osnvram"/>
+ <choice>
+ <ref name="osnvram"/>
+ <ref name="osvarstore"/>
+ </choice>
</optional>
<optional>
<ref name="osbootkernel"/>
@@ -456,6 +459,23 @@
</element>
</define>
+ <define name="osvarstore">
+ <element name="varstore">
+ <interleave>
+ <optional>
+ <attribute name="template">
+ <ref name="absFilePath"/>
+ </attribute>
+ </optional>
+ <optional>
+ <attribute name="path">
+ <ref name="absFilePath"/>
+ </attribute>
+ </optional>
+ </interleave>
+ </element>
+ </define>
+
<define name="osexe">
<element name="os">
<interleave>
diff --git a/src/conf/virconftypes.h b/src/conf/virconftypes.h
index 6e2573035a..0596791a4d 100644
--- a/src/conf/virconftypes.h
+++ b/src/conf/virconftypes.h
@@ -164,6 +164,8 @@ typedef struct _virDomainLeaseDef virDomainLeaseDef;
typedef struct _virDomainLoaderDef virDomainLoaderDef;
+typedef struct _virDomainVarstoreDef virDomainVarstoreDef;
+
typedef struct _virDomainMemballoonDef virDomainMemballoonDef;
typedef struct _virDomainMemoryDef virDomainMemoryDef;
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index effe44fe57..1308fa2e51 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -718,6 +718,8 @@ virDomainTPMProfileRemoveDisabledTypeToString;
virDomainTPMVersionTypeFromString;
virDomainTPMVersionTypeToString;
virDomainUSBDeviceDefForeach;
+virDomainVarstoreDefFree;
+virDomainVarstoreDefNew;
virDomainVideoDefaultRAM;
virDomainVideoDefClear;
virDomainVideoDefFree;
--
2.53.0

View File

@ -0,0 +1,378 @@
From f47031d4e6439d1daf5711d4117c0fa647196944 Mon Sep 17 00:00:00 2001
Message-ID: <f47031d4e6439d1daf5711d4117c0fa647196944.1772815313.git.jdenemar@redhat.com>
From: Andrea Bolognani <abologna@redhat.com>
Date: Thu, 22 Jan 2026 19:27:03 +0100
Subject: [PATCH] conf: Update validation to consider varstore element
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The code is reworked quite significantly, but most of the
existing checks are preserved. Those that aren't, notably the
one that allowed pflash as the only acceptable non-stateless
firmware type, are intentionally removed because they will no
longer reflect reality once support for the uefi-vars QEMU
device is introduced.
As a side effect, reworking the function in this fashion
resolves a subtle bug: due to the early exits that were being
performed when the loader element was missing, the checks at
the bottom of the function (related to the shim and kernel
elements) were effectively never performed. This is no longer
the case.
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
(cherry picked from commit 1c2dbdf3ac5bed84caeacf585d5143dcf32df75e)
https://issues.redhat.com/browse/RHEL-82645
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
---
src/conf/domain_validate.c | 100 +++++++-----------
...-auto-bios-not-stateless.x86_64-latest.err | 2 +-
...-auto-bios-not-stateless.x86_64-latest.xml | 35 ++++++
...firmware-auto-bios-nvram.x86_64-latest.err | 2 +-
...nual-bios-not-stateless.x86_64-latest.args | 32 ++++++
...anual-bios-not-stateless.x86_64-latest.err | 1 -
...anual-bios-not-stateless.x86_64-latest.xml | 28 +++++
...nual-efi-nvram-stateless.x86_64-latest.err | 2 +-
...nvram-template-stateless.x86_64-latest.err | 2 +-
...ware-manual-efi-rw-nvram.x86_64-latest.err | 2 +-
tests/qemuxmlconftest.c | 7 +-
11 files changed, 144 insertions(+), 69 deletions(-)
create mode 100644 tests/qemuxmlconfdata/firmware-auto-bios-not-stateless.x86_64-latest.xml
create mode 100644 tests/qemuxmlconfdata/firmware-manual-bios-not-stateless.x86_64-latest.args
delete mode 100644 tests/qemuxmlconfdata/firmware-manual-bios-not-stateless.x86_64-latest.err
create mode 100644 tests/qemuxmlconfdata/firmware-manual-bios-not-stateless.x86_64-latest.xml
diff --git a/src/conf/domain_validate.c b/src/conf/domain_validate.c
index 7346a61731..163095d55c 100644
--- a/src/conf/domain_validate.c
+++ b/src/conf/domain_validate.c
@@ -1723,95 +1723,46 @@ virDomainDefOSValidate(const virDomainDef *def,
virDomainXMLOption *xmlopt)
{
virDomainLoaderDef *loader = def->os.loader;
+ virDomainVarstoreDef *varstore = def->os.varstore;
+ virDomainOsDefFirmware firmware = def->os.firmware;
+ int *firmwareFeatures = def->os.firmwareFeatures;
+ bool usesNvram = loader && (loader->nvram || loader->nvramTemplate || loader->nvramTemplateFormat);
- if (def->os.firmware) {
+ if (firmware) {
if (xmlopt && !(xmlopt->config.features & VIR_DOMAIN_DEF_FEATURE_FW_AUTOSELECT)) {
virReportError(VIR_ERR_XML_DETAIL, "%s",
_("firmware auto selection not implemented for this driver"));
return -1;
}
- if (def->os.firmwareFeatures &&
- def->os.firmwareFeatures[VIR_DOMAIN_OS_DEF_FIRMWARE_FEATURE_ENROLLED_KEYS] == VIR_TRISTATE_BOOL_YES &&
- def->os.firmwareFeatures[VIR_DOMAIN_OS_DEF_FIRMWARE_FEATURE_SECURE_BOOT] == VIR_TRISTATE_BOOL_NO) {
+ if (firmwareFeatures &&
+ firmwareFeatures[VIR_DOMAIN_OS_DEF_FIRMWARE_FEATURE_ENROLLED_KEYS] == VIR_TRISTATE_BOOL_YES &&
+ firmwareFeatures[VIR_DOMAIN_OS_DEF_FIRMWARE_FEATURE_SECURE_BOOT] == VIR_TRISTATE_BOOL_NO) {
virReportError(VIR_ERR_XML_DETAIL, "%s",
_("firmware feature 'enrolled-keys' cannot be enabled when firmware feature 'secure-boot' is disabled"));
return -1;
}
-
- if (!loader)
- return 0;
-
- if (loader->nvram && def->os.firmware != VIR_DOMAIN_OS_DEF_FIRMWARE_EFI) {
- virReportError(VIR_ERR_XML_DETAIL,
- _("firmware type '%1$s' does not support nvram"),
- virDomainOsDefFirmwareTypeToString(def->os.firmware));
- return -1;
- }
} else {
- if (def->os.firmwareFeatures) {
+ if (firmwareFeatures) {
virReportError(VIR_ERR_XML_DETAIL, "%s",
_("cannot use feature-based firmware autoselection when firmware autoselection is disabled"));
return -1;
}
- if (!loader)
- return 0;
-
- if (!loader->path) {
+ if (loader && !loader->path) {
virReportError(VIR_ERR_XML_DETAIL, "%s",
_("no loader path specified and firmware auto selection disabled"));
return -1;
}
}
- if (loader->readonly == VIR_TRISTATE_BOOL_NO) {
- if (loader->type == VIR_DOMAIN_LOADER_TYPE_ROM) {
+ if (loader && loader->type == VIR_DOMAIN_LOADER_TYPE_ROM) {
+ if (loader->readonly == VIR_TRISTATE_BOOL_NO) {
virReportError(VIR_ERR_XML_DETAIL, "%s",
_("ROM loader type cannot be used as read/write"));
return -1;
}
- if (loader->nvramTemplate) {
- virReportError(VIR_ERR_XML_DETAIL, "%s",
- _("NVRAM template is not permitted when loader is read/write"));
- return -1;
- }
-
- if (loader->nvram) {
- virReportError(VIR_ERR_XML_DETAIL, "%s",
- _("NVRAM is not permitted when loader is read/write"));
- return -1;
- }
- }
-
- if (loader->stateless == VIR_TRISTATE_BOOL_YES) {
- if (loader->nvramTemplate) {
- virReportError(VIR_ERR_XML_DETAIL, "%s",
- _("NVRAM template is not permitted when loader is stateless"));
- return -1;
- }
-
- if (loader->nvram) {
- virReportError(VIR_ERR_XML_DETAIL, "%s",
- _("NVRAM is not permitted when loader is stateless"));
- return -1;
- }
- } else if (loader->stateless == VIR_TRISTATE_BOOL_NO) {
- if (def->os.firmware == VIR_DOMAIN_OS_DEF_FIRMWARE_NONE) {
- if (def->os.loader->type != VIR_DOMAIN_LOADER_TYPE_PFLASH) {
- virReportError(VIR_ERR_XML_DETAIL, "%s",
- _("Only pflash loader type permits NVRAM"));
- return -1;
- }
- } else if (def->os.firmware != VIR_DOMAIN_OS_DEF_FIRMWARE_EFI) {
- virReportError(VIR_ERR_XML_DETAIL, "%s",
- _("Only EFI firmware permits NVRAM"));
- return -1;
- }
- }
-
- if (loader->type == VIR_DOMAIN_LOADER_TYPE_ROM) {
if (loader->format &&
loader->format != VIR_STORAGE_FILE_RAW) {
virReportError(VIR_ERR_XML_DETAIL,
@@ -1821,6 +1772,33 @@ virDomainDefOSValidate(const virDomainDef *def,
}
}
+ if (usesNvram && varstore) {
+ virReportError(VIR_ERR_XML_DETAIL, "%s",
+ _("Only one of NVRAM/varstore can be used"));
+ return -1;
+ }
+
+ if (usesNvram || varstore) {
+ if (firmware && firmware != VIR_DOMAIN_OS_DEF_FIRMWARE_EFI) {
+ virReportError(VIR_ERR_XML_DETAIL,
+ _("Firmware type '%1$s' does not support variable storage (NVRAM/varstore)"),
+ virDomainOsDefFirmwareTypeToString(firmware));
+ return -1;
+ }
+
+ if (loader && loader->stateless == VIR_TRISTATE_BOOL_YES) {
+ virReportError(VIR_ERR_XML_DETAIL, "%s",
+ _("Variable storage (NVRAM/varstore) is not permitted when loader is stateless"));
+ return -1;
+ }
+
+ if (loader && loader->readonly == VIR_TRISTATE_BOOL_NO) {
+ virReportError(VIR_ERR_XML_DETAIL, "%s",
+ _("Variable storage (NVRAM/varstore) is not permitted when loader is read/write"));
+ return -1;
+ }
+ }
+
if (def->os.shim && !def->os.kernel) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("shim only allowed with kernel option"));
diff --git a/tests/qemuxmlconfdata/firmware-auto-bios-not-stateless.x86_64-latest.err b/tests/qemuxmlconfdata/firmware-auto-bios-not-stateless.x86_64-latest.err
index b058f970a4..743fe27a97 100644
--- a/tests/qemuxmlconfdata/firmware-auto-bios-not-stateless.x86_64-latest.err
+++ b/tests/qemuxmlconfdata/firmware-auto-bios-not-stateless.x86_64-latest.err
@@ -1 +1 @@
-Only EFI firmware permits NVRAM
+operation failed: Unable to find 'bios' firmware that is compatible with the current configuration
diff --git a/tests/qemuxmlconfdata/firmware-auto-bios-not-stateless.x86_64-latest.xml b/tests/qemuxmlconfdata/firmware-auto-bios-not-stateless.x86_64-latest.xml
new file mode 100644
index 0000000000..062835e351
--- /dev/null
+++ b/tests/qemuxmlconfdata/firmware-auto-bios-not-stateless.x86_64-latest.xml
@@ -0,0 +1,35 @@
+<domain type='kvm'>
+ <name>guest</name>
+ <uuid>63840878-0deb-4095-97e6-fc444d9bc9fa</uuid>
+ <memory unit='KiB'>1048576</memory>
+ <currentMemory unit='KiB'>1048576</currentMemory>
+ <vcpu placement='static'>1</vcpu>
+ <os firmware='bios'>
+ <type arch='x86_64' machine='pc-q35-10.0'>hvm</type>
+ <loader stateless='no' format='raw'/>
+ <boot dev='hd'/>
+ </os>
+ <features>
+ <acpi/>
+ </features>
+ <cpu mode='custom' match='exact' check='none'>
+ <model fallback='forbid'>qemu64</model>
+ </cpu>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <emulator>/usr/bin/qemu-system-x86_64</emulator>
+ <controller type='usb' index='0' model='none'/>
+ <controller type='sata' index='0'>
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x1f' function='0x2'/>
+ </controller>
+ <controller type='pci' index='0' model='pcie-root'/>
+ <input type='mouse' bus='ps2'/>
+ <input type='keyboard' bus='ps2'/>
+ <audio id='1' type='none'/>
+ <watchdog model='itco' action='reset'/>
+ <memballoon model='none'/>
+ </devices>
+</domain>
diff --git a/tests/qemuxmlconfdata/firmware-auto-bios-nvram.x86_64-latest.err b/tests/qemuxmlconfdata/firmware-auto-bios-nvram.x86_64-latest.err
index 772beb49e2..c4eeb92788 100644
--- a/tests/qemuxmlconfdata/firmware-auto-bios-nvram.x86_64-latest.err
+++ b/tests/qemuxmlconfdata/firmware-auto-bios-nvram.x86_64-latest.err
@@ -1 +1 @@
-firmware type 'bios' does not support nvram
+Firmware type 'bios' does not support variable storage (NVRAM/varstore)
diff --git a/tests/qemuxmlconfdata/firmware-manual-bios-not-stateless.x86_64-latest.args b/tests/qemuxmlconfdata/firmware-manual-bios-not-stateless.x86_64-latest.args
new file mode 100644
index 0000000000..969c7ad68c
--- /dev/null
+++ b/tests/qemuxmlconfdata/firmware-manual-bios-not-stateless.x86_64-latest.args
@@ -0,0 +1,32 @@
+LC_ALL=C \
+PATH=/bin \
+HOME=/var/lib/libvirt/qemu/domain--1-guest \
+USER=test \
+LOGNAME=test \
+XDG_DATA_HOME=/var/lib/libvirt/qemu/domain--1-guest/.local/share \
+XDG_CACHE_HOME=/var/lib/libvirt/qemu/domain--1-guest/.cache \
+XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-guest/.config \
+/usr/bin/qemu-system-x86_64 \
+-name guest=guest,debug-threads=on \
+-S \
+-object '{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/var/lib/libvirt/qemu/domain--1-guest/master-key.aes"}' \
+-machine pc-i440fx-10.0,usb=off,dump-guest-core=off,memory-backend=pc.ram,acpi=off \
+-accel tcg \
+-cpu qemu64 \
+-bios /usr/share/seabios/bios.bin \
+-m size=1048576k \
+-object '{"qom-type":"memory-backend-ram","id":"pc.ram","size":1073741824}' \
+-overcommit mem-lock=off \
+-smp 1,sockets=1,cores=1,threads=1 \
+-uuid 63840878-0deb-4095-97e6-fc444d9bc9fa \
+-display none \
+-no-user-config \
+-nodefaults \
+-chardev socket,id=charmonitor,fd=1729,server=on,wait=off \
+-mon chardev=charmonitor,id=monitor,mode=control \
+-rtc base=utc \
+-no-shutdown \
+-boot strict=on \
+-audiodev '{"id":"audio1","driver":"none"}' \
+-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \
+-msg timestamp=on
diff --git a/tests/qemuxmlconfdata/firmware-manual-bios-not-stateless.x86_64-latest.err b/tests/qemuxmlconfdata/firmware-manual-bios-not-stateless.x86_64-latest.err
deleted file mode 100644
index 188a5a4180..0000000000
--- a/tests/qemuxmlconfdata/firmware-manual-bios-not-stateless.x86_64-latest.err
+++ /dev/null
@@ -1 +0,0 @@
-Only pflash loader type permits NVRAM
diff --git a/tests/qemuxmlconfdata/firmware-manual-bios-not-stateless.x86_64-latest.xml b/tests/qemuxmlconfdata/firmware-manual-bios-not-stateless.x86_64-latest.xml
new file mode 100644
index 0000000000..075da36d00
--- /dev/null
+++ b/tests/qemuxmlconfdata/firmware-manual-bios-not-stateless.x86_64-latest.xml
@@ -0,0 +1,28 @@
+<domain type='qemu'>
+ <name>guest</name>
+ <uuid>63840878-0deb-4095-97e6-fc444d9bc9fa</uuid>
+ <memory unit='KiB'>1048576</memory>
+ <currentMemory unit='KiB'>1048576</currentMemory>
+ <vcpu placement='static'>1</vcpu>
+ <os>
+ <type arch='x86_64' machine='pc-i440fx-10.0'>hvm</type>
+ <loader type='rom' stateless='no' format='raw'>/usr/share/seabios/bios.bin</loader>
+ <boot dev='hd'/>
+ </os>
+ <cpu mode='custom' match='exact' check='none'>
+ <model fallback='forbid'>qemu64</model>
+ </cpu>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <emulator>/usr/bin/qemu-system-x86_64</emulator>
+ <controller type='usb' index='0' model='none'/>
+ <controller type='pci' index='0' model='pci-root'/>
+ <input type='mouse' bus='ps2'/>
+ <input type='keyboard' bus='ps2'/>
+ <audio id='1' type='none'/>
+ <memballoon model='none'/>
+ </devices>
+</domain>
diff --git a/tests/qemuxmlconfdata/firmware-manual-efi-nvram-stateless.x86_64-latest.err b/tests/qemuxmlconfdata/firmware-manual-efi-nvram-stateless.x86_64-latest.err
index de8db3763d..9bfd4465ab 100644
--- a/tests/qemuxmlconfdata/firmware-manual-efi-nvram-stateless.x86_64-latest.err
+++ b/tests/qemuxmlconfdata/firmware-manual-efi-nvram-stateless.x86_64-latest.err
@@ -1 +1 @@
-NVRAM is not permitted when loader is stateless
+Variable storage (NVRAM/varstore) is not permitted when loader is stateless
diff --git a/tests/qemuxmlconfdata/firmware-manual-efi-nvram-template-stateless.x86_64-latest.err b/tests/qemuxmlconfdata/firmware-manual-efi-nvram-template-stateless.x86_64-latest.err
index 95ec794c17..9bfd4465ab 100644
--- a/tests/qemuxmlconfdata/firmware-manual-efi-nvram-template-stateless.x86_64-latest.err
+++ b/tests/qemuxmlconfdata/firmware-manual-efi-nvram-template-stateless.x86_64-latest.err
@@ -1 +1 @@
-NVRAM template is not permitted when loader is stateless
+Variable storage (NVRAM/varstore) is not permitted when loader is stateless
diff --git a/tests/qemuxmlconfdata/firmware-manual-efi-rw-nvram.x86_64-latest.err b/tests/qemuxmlconfdata/firmware-manual-efi-rw-nvram.x86_64-latest.err
index d0cf62061a..708b4838d4 100644
--- a/tests/qemuxmlconfdata/firmware-manual-efi-rw-nvram.x86_64-latest.err
+++ b/tests/qemuxmlconfdata/firmware-manual-efi-rw-nvram.x86_64-latest.err
@@ -1 +1 @@
-NVRAM is not permitted when loader is read/write
+Variable storage (NVRAM/varstore) is not permitted when loader is read/write
diff --git a/tests/qemuxmlconftest.c b/tests/qemuxmlconftest.c
index 822e29b888..a3d4d2de5c 100644
--- a/tests/qemuxmlconftest.c
+++ b/tests/qemuxmlconftest.c
@@ -1575,7 +1575,10 @@ mymain(void)
DO_TEST_CAPS_LATEST("firmware-manual-bios");
DO_TEST_CAPS_LATEST("firmware-manual-bios-stateless");
- DO_TEST_CAPS_LATEST_PARSE_ERROR("firmware-manual-bios-not-stateless");
+ /* This combination doesn't make sense (BIOS is stateless by definition)
+ * but unfortunately there's no way for libvirt to report an error in this
+ * scenario. The stateless=no attribute will effectively be ignored */
+ DO_TEST_CAPS_LATEST("firmware-manual-bios-not-stateless");
DO_TEST_CAPS_LATEST_PARSE_ERROR("firmware-manual-bios-rw");
DO_TEST_CAPS_LATEST("firmware-manual-efi");
DO_TEST_CAPS_LATEST("firmware-manual-efi-features");
@@ -1628,7 +1631,7 @@ mymain(void)
DO_TEST_CAPS_LATEST("firmware-auto-bios");
DO_TEST_CAPS_LATEST("firmware-auto-bios-stateless");
DO_TEST_CAPS_LATEST_FAILURE("firmware-auto-bios-rw");
- DO_TEST_CAPS_LATEST_PARSE_ERROR("firmware-auto-bios-not-stateless");
+ DO_TEST_CAPS_LATEST_FAILURE("firmware-auto-bios-not-stateless");
DO_TEST_CAPS_LATEST_PARSE_ERROR("firmware-auto-bios-nvram");
DO_TEST_CAPS_LATEST("firmware-auto-efi");
DO_TEST_CAPS_LATEST_ABI_UPDATE("firmware-auto-efi");
--
2.53.0

View File

@ -0,0 +1,88 @@
From 8754c491f66e5d13290aaf221a29b19bd855a171 Mon Sep 17 00:00:00 2001
Message-ID: <8754c491f66e5d13290aaf221a29b19bd855a171.1772815313.git.jdenemar@redhat.com>
From: Andrea Bolognani <abologna@redhat.com>
Date: Wed, 11 Feb 2026 00:48:18 +0100
Subject: [PATCH] docs: Document firmwareFeature element for domaincaps
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit cf4dfcf7951779a815324adebcdaa8a845d4c0e1)
https://issues.redhat.com/browse/RHEL-82645
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
---
docs/formatdomaincaps.rst | 51 +++++++++++++++++++++++++++++++++++++++
1 file changed, 51 insertions(+)
diff --git a/docs/formatdomaincaps.rst b/docs/formatdomaincaps.rst
index 6ba7f84f96..cca827923c 100644
--- a/docs/formatdomaincaps.rst
+++ b/docs/formatdomaincaps.rst
@@ -111,6 +111,16 @@ be passed to its children.
<value>bios</value>
<value>efi</value>
</enum>
+ <firmwareFeatures supported='yes'>
+ <enum name='secureBoot'>
+ <value>yes</value>
+ <value>no</value>
+ </enum>
+ <enum name='enrolledKeys'>
+ <value>yes</value>
+ <value>no</value>
+ </enum>
+ </firmwareFeatures>
<loader supported='yes'>
<value>/usr/share/OVMF/OVMF_CODE.fd</value>
<enum name='type'>
@@ -140,6 +150,47 @@ about a given BIOS or UEFI binary on the host, e.g. the firmware binary path,
its architecture, supported machine types, NVRAM template, etc. This ensures
that the reported values won't cause a failure on guest boot.
+The ``<firmwareFeatures/>`` element :since:`(since 12.1.0)` contains one
+enum for each of the features that can be used to fine-tune the firmware
+autoselection process. For example:
+
+::
+
+ <firmwareFeatures supported='yes'>
+ <enum name='secureBoot'>
+ <value>yes</value>
+ </enum>
+ <enum name='enrolledKeys'>
+ <value>yes</value>
+ <value>no</value>
+ </enum>
+ </firmwareFeatures>
+
+indicates that a domain XML such as:
+
+::
+
+ <os firmware='efi'>
+ <firmware>
+ <feature name='secure-boot' enabled='yes'/>
+ <feature name='enrolled-keys' enabled='no'/>
+ </firmware>
+ </os>
+
+can be used to allow unsigned operating system to run, whereas a domain XML
+such as:
+
+::
+
+ <os firmware='efi'>
+ <firmware>
+ <feature name='secure-boot' enabled='no'/>
+ </firmware>
+ </os>
+
+would not work, since ``no`` is not one of the valid values advertised by
+the ``secureBoot`` enum.
+
For the ``loader`` element, the following can occur:
``value``
--
2.53.0

View File

@ -0,0 +1,109 @@
From 495763256a6e10ff90210d54efd53f1d4f9e2544 Mon Sep 17 00:00:00 2001
Message-ID: <495763256a6e10ff90210d54efd53f1d4f9e2544.1772815313.git.jdenemar@redhat.com>
From: Andrea Bolognani <abologna@redhat.com>
Date: Mon, 23 Feb 2026 14:58:15 +0100
Subject: [PATCH] docs: Improvement related to firmware selection
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Recommend that users take advantage of firmware autoselection
and discourage providing paths manually.
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
(cherry picked from commit a03a8205725efec69b1fc7cc0318fa6ce79b6aa9)
https://issues.redhat.com/browse/RHEL-82645
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
---
docs/formatdomaincaps.rst | 59 ++++++++++++++++++++++-----------------
1 file changed, 34 insertions(+), 25 deletions(-)
diff --git a/docs/formatdomaincaps.rst b/docs/formatdomaincaps.rst
index 22a6d5d067..3426b7c9cd 100644
--- a/docs/formatdomaincaps.rst
+++ b/docs/formatdomaincaps.rst
@@ -145,15 +145,17 @@ domains.
...
<domainCapabilities>
-The ``firmware`` enum corresponds to the ``firmware`` attribute of the ``os``
-element in the domain XML. The presence of this enum means libvirt is capable of
-the so-called firmware auto-selection feature. And the listed firmware values
-represent the accepted input in the domain XML. Note that the ``firmware`` enum
-reports only those values for which a firmware "descriptor file" exists on the
-host. Firmware descriptor file is a small JSON document that describes details
-about a given BIOS or UEFI binary on the host, e.g. the firmware binary path,
-its architecture, supported machine types, NVRAM template, etc. This ensures
-that the reported values won't cause a failure on guest boot.
+The presence of the ``firmware`` enum means that libvirt can perform firmware
+autoselection, and each of the values is guaranteed to be usable. In the
+domain XML, firmware autoselection is enabled as follows:
+
+::
+
+ <os firmware='efi'>
+ ...
+
+Autoselection is the recommended mechanism for configuring the guest firmware.
+Providing paths and other information manually is discouraged.
The ``<firmwareFeatures/>`` element :since:`(since 12.1.0)` contains one
enum for each of the features that can be used to fine-tune the firmware
@@ -196,27 +198,34 @@ such as:
would not work, since ``no`` is not one of the valid values advertised by
the ``secureBoot`` enum.
-For the ``loader`` element, the following can occur:
+The information contained in the ``<loader/>`` element is not relevant when
+using firmware autoselection, which is the recommended approach to guest
+firmware configuration, and as such can largely be ignored. Its subelements
+are the following:
``value``
- List of known firmware binary paths. Currently this is used only to advertise
- the known location of OVMF binaries for QEMU. OVMF binaries will only be
- listed if they actually exist on host.
+ One element for each known firmware binary present on the system.
+
+ Note that a binary being present here indicates that the file exists and it
+ is compatible with the architecture/machine type, but does not provide any
+ insight into which mechanism (see ``type`` below) should be used to load it.
``type``
- Whether the boot loader is a typical BIOS (``rom``) or a UEFI firmware
- (``pflash``). Each ``value`` sub-element under the ``type`` enum represents a
- possible value for the ``type`` attribute for the <loader/> element in the
- domain XML. E.g. the presence of ``pfalsh`` under the ``type`` enum means
- that a domain XML can use UEFI firmware via: <loader/> type="pflash"
- ...>/path/to/the/firmware/binary/</loader>.
+ Whether firmware can be loaded using a ``pflash`` device (UEFI only) or as
+ a ``rom`` (either UEFI or BIOS).
``readonly``
- Options for the ``readonly`` attribute of the <loader/> element in the domain
- XML.
+ Supported values for the ``readonly`` attribute of the ``<loader/>`` element
+ in the domain XML.
``secure``
- Options for the ``secure`` attribute of the <loader/> element in the domain
- XML. Note that the value ``yes`` is listed only if libvirt detects a firmware
- descriptor file that has path to an OVMF binary that supports Secure boot,
- and lists its architecture and supported machine type.
+ Supported values for the ``secure`` attribute of the ``<loader/>`` element
+ in the domain XML.
+
+ Note that the value ``yes`` is listed if libvirt detects a firmware
+ descriptor file that points to a firmware binary that implements Secure
+ Boot and is compatible with the architecture/machine type, but the UEFI
+ variable store template associated with it might not have the usual set of
+ Secure Boot certificates enrolled. To figure out whether it's actually
+ possible to enforce Secure Boot, look at the ``enrolledKeys`` enum inside
+ the ``<firmwareFeatures/>`` element instead.
CPU configuration
~~~~~~~~~~~~~~~~~
--
2.53.0

View File

@ -0,0 +1,159 @@
From 807dfc5b7ce3d77d7343b896082d2ae3395b3fdc Mon Sep 17 00:00:00 2001
Message-ID: <807dfc5b7ce3d77d7343b896082d2ae3395b3fdc.1772815313.git.jdenemar@redhat.com>
From: Andrea Bolognani <abologna@redhat.com>
Date: Mon, 23 Feb 2026 14:55:20 +0100
Subject: [PATCH] docs: Rename "BIOS bootloader" section to "guest firmware"
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The new name is much more accurate since the documentation is
applicable to firmware other than BIOS, notably UEFI.
An empty container is used to keep old links working.
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
(cherry picked from commit 38379f59c0d26d006414a1fd92bdf332dadd1ddd)
https://issues.redhat.com/browse/RHEL-82645
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
---
docs/formatcaps.rst | 2 +-
docs/formatdomain.rst | 24 ++++++++++++++----------
docs/formatdomaincaps.rst | 19 ++++++++++++-------
3 files changed, 27 insertions(+), 18 deletions(-)
diff --git a/docs/formatcaps.rst b/docs/formatcaps.rst
index fa8ab5197f..9458e1289a 100644
--- a/docs/formatcaps.rst
+++ b/docs/formatcaps.rst
@@ -172,7 +172,7 @@ The ``<guest/>`` element will typically wrap up the following elements:
Emulator (device model) path, for use in
`emulator <formatdomain.html#devices>`__ element of domain XML.
``loader``
- Loader path, for use in `loader <formatdomain.html#bios-bootloader>`__
+ Loader path, for use in `loader <formatdomain.html#guest-firmware>`__
element of domain XML.
``machine``
Machine type, for use in
diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst
index 31232deb3c..152fd7f530 100644
--- a/docs/formatdomain.rst
+++ b/docs/formatdomain.rst
@@ -103,12 +103,16 @@ Operating system booting
There are a number of different ways to boot virtual machines each with their
own pros and cons.
+Guest firmware
+~~~~~~~~~~~~~~
-BIOS bootloader
-~~~~~~~~~~~~~~~
+.. container::
+ :name: bios-bootloader
-Booting via the BIOS is available for hypervisors supporting full
-virtualization. In this case the BIOS has a boot order priority (floppy,
+ .. this container only exists to keep old links working
+
+Booting via a guest firmware is available for hypervisors supporting full
+virtualization. In this case the firmware has a boot order priority (floppy,
harddisk, cdrom, network) determining where to obtain/find the boot image.
::
@@ -411,10 +415,10 @@ and full virtualized guests.
``type``
This element has the same semantics as described earlier in the
- `BIOS bootloader`_ section.
+ `guest firmware`_ section.
``loader``
This element has the same semantics as described earlier in the
- `BIOS bootloader`_ section.
+ `guest firmware`_ section.
``kernel``
The contents of this element specify the fully-qualified path to the kernel
image in the host OS.
@@ -3732,7 +3736,7 @@ paravirtualized driver is specified via the ``disk`` element.
attribute is an 8 character string which can be queried by guests on S390 via
sclp or diag 308. Linux guests on S390 can use ``loadparm`` to select a boot
entry. :since:`Since 3.5.0` The per-device ``boot`` elements cannot be used
- together with general boot elements in `BIOS bootloader`_
+ together with general boot elements in `guest firmware`_
section. :since:`Since 0.8.8`
``encryption``
since:`Since 3.9.0` the ``encryption`` element is preferred
@@ -4897,7 +4901,7 @@ or:
Specifies that the device is bootable. The ``order`` attribute determines the
order in which devices will be tried during boot sequence. The per-device
``boot`` elements cannot be used together with general boot elements in
- `BIOS bootloader`_ section. :since:`Since 0.8.8` for PCI
+ `guest firmware`_ section. :since:`Since 0.8.8` for PCI
devices, :since:`Since 1.0.1` for USB devices.
``rom``
The ``rom`` element is used to change how a PCI device's ROM is presented to
@@ -5121,7 +5125,7 @@ USB device redirection through a character device is supported
Specifies that the device is bootable. The ``order`` attribute determines the
order in which devices will be tried during boot sequence. The per-device
``boot`` elements cannot be used together with general boot elements in
- `BIOS bootloader`_ section. ( :since:`Since 1.0.1` )
+ `guest firmware`_ section. ( :since:`Since 1.0.1` )
``redirfilter``
The\ ``redirfilter``\ element is used for creating the filter rule to filter
out certain devices from redirection. It uses sub-element ``<usbdev>`` to
@@ -6377,7 +6381,7 @@ Specifying boot order
For hypervisors which support this, you can set a specific NIC to be used for
network boot. The ``order`` attribute determines the order in which devices will
be tried during boot sequence. The per-device ``boot`` elements cannot be used
-together with general boot elements in `BIOS bootloader`_
+together with general boot elements in `guest firmware`_
section. :since:`Since 0.8.8`
Interface ROM BIOS configuration
diff --git a/docs/formatdomaincaps.rst b/docs/formatdomaincaps.rst
index cca827923c..22a6d5d067 100644
--- a/docs/formatdomaincaps.rst
+++ b/docs/formatdomaincaps.rst
@@ -72,11 +72,11 @@ The root element that emulator capability XML document starts with has name
Describes the `virtualization type <formatdomain.html#element-and-attribute-overview>`__ (or so
called domain type).
``machine``
- The domain's `machine type <formatdomain.html#bios-bootloader>`__. Since not
+ The domain's `machine type <formatdomain.html#guest-firmware>`__. Since not
every hypervisor has a sense of machine types this element might be omitted
in such drivers.
``arch``
- The domain's `architecture <formatdomain.html#bios-bootloader>`__.
+ The domain's `architecture <formatdomain.html#guest-firmware>`__.
CPU Allocation
~~~~~~~~~~~~~~
@@ -95,12 +95,17 @@ capabilities, e.g. virtual CPUs:
``vcpu``
The maximum number of supported virtual CPUs
-BIOS bootloader
-~~~~~~~~~~~~~~~
+Guest firmware
+~~~~~~~~~~~~~~
-Sometimes users might want to tweak some BIOS knobs or use UEFI. For cases like
-that, `os <formatdomain.html#bios-bootloader>`__ element exposes what values can
-be passed to its children.
+.. container::
+ :name: bios-bootloader
+
+ .. this container only exists to keep old links working
+
+Exposes information about supported
+`guest firmware <formatdomain.html#guest-firmware>`__ configurations for
+domains.
::
--
2.53.0

View File

@ -0,0 +1,62 @@
From f6268acd96651ce72014e2ea7ed649caff0b9133 Mon Sep 17 00:00:00 2001
Message-ID: <f6268acd96651ce72014e2ea7ed649caff0b9133.1771336681.git.jdenemar@redhat.com>
From: Peter Krempa <pkrempa@redhat.com>
Date: Fri, 30 Jan 2026 17:47:46 +0100
Subject: [PATCH] docs: formatdomain: Fix indentation of docs for
<disk><driver><statistics> element
All other paragraphs in this section use 2 spaces after hyphen, fix the
recently added section.
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit 7da1a83914ca10cc811583d7310bf60e04b70488)
https://issues.redhat.com/browse/RHEL-147866 [rhel-9.8]
https://issues.redhat.com/browse/RHEL-131335 [rhel-10.2]
---
docs/formatdomain.rst | 26 +++++++++++++-------------
1 file changed, 13 insertions(+), 13 deletions(-)
diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst
index 9836837441..45f262113b 100644
--- a/docs/formatdomain.rst
+++ b/docs/formatdomain.rst
@@ -3605,22 +3605,22 @@ paravirtualized driver is specified via the ``disk`` element.
</iothreads>
</driver>
- - The optional ``statistics`` sub-element allows configuring statistics
- collection in configurable intervals for the given disk. Intervals are
- configured by ``<statistic>`` sub-elements with ``interval`` attribute
- configuring the collection window duration in seconds. The statistics
- are available via the bulk statistics API.
+ - The optional ``statistics`` sub-element allows configuring statistics
+ collection in configurable intervals for the given disk. Intervals are
+ configured by ``<statistic>`` sub-elements with ``interval`` attribute
+ configuring the collection window duration in seconds. The statistics
+ are available via the bulk statistics API.
- Example::
+ Example::
- <driver name='qemu'>
- <statistics>
- <statistic interval='1'/>
- <statistic interval='10'/>
- </statistics>
- </driver>
+ <driver name='qemu'>
+ <statistics>
+ <statistic interval='1'/>
+ <statistic interval='10'/>
+ </statistics>
+ </driver>
- :since:`Since 11.9.0 (QEMU 10.2, virtio, ide, scsi disks only)`.
+ :since:`Since 11.9.0 (QEMU 10.2, virtio, ide, scsi disks only)`.
- The optional ``queues`` attribute specifies the number of virt queues for
virtio-blk ( :since:`Since 3.9.0` ) or vhost-user-blk
--
2.53.0

View File

@ -0,0 +1,51 @@
From ea6f8a96929577416a5cc4f4452f920312aef081 Mon Sep 17 00:00:00 2001
Message-ID: <ea6f8a96929577416a5cc4f4452f920312aef081.1771336682.git.jdenemar@redhat.com>
From: Peter Krempa <pkrempa@redhat.com>
Date: Fri, 30 Jan 2026 17:37:48 +0100
Subject: [PATCH] docs: formatdomain: Reword section about the '<statistics>'
element under disk driver
Separate the timed statistics group and link to the fields which are
returned by it.
Prepare the wording for more statistics configs in the future.
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit ad65b00c1393f7f13e15744e2e1be4fb531e2a17)
https://issues.redhat.com/browse/RHEL-147866 [rhel-9.8]
https://issues.redhat.com/browse/RHEL-131335 [rhel-10.2]
---
docs/formatdomain.rst | 16 +++++++++++-----
1 file changed, 11 insertions(+), 5 deletions(-)
diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst
index 45f262113b..70882c6820 100644
--- a/docs/formatdomain.rst
+++ b/docs/formatdomain.rst
@@ -3605,11 +3605,17 @@ paravirtualized driver is specified via the ``disk`` element.
</iothreads>
</driver>
- - The optional ``statistics`` sub-element allows configuring statistics
- collection in configurable intervals for the given disk. Intervals are
- configured by ``<statistic>`` sub-elements with ``interval`` attribute
- configuring the collection window duration in seconds. The statistics
- are available via the bulk statistics API.
+ - The optional ``statistics`` sub-element allows configuring various optional
+ statistics collection.
+
+ Statistic values returned under
+ `VIR_DOMAIN_STATS_BLOCK_SUFFIX_TIMED_GROUP_PREFIX <html/libvirt-libvirt-domain.html#VIR_DOMAIN_STATS_BLOCK_SUFFIX_TIMED_GROUP_PREFIX>`__
+ typed parameter prefix returned by the
+ `virConnectGetAllDomainStats <html/libvirt-libvirt-domain.html#virConnectGetAllDomainStats>`__
+ API are collected based on one or more configurable intervals. An interval
+ of collection is configured by ``<statistic>`` sub-elements with
+ ``interval`` attribute configuring the collection window duration in
+ seconds.
Example::
--
2.53.0

View File

@ -0,0 +1,94 @@
From 96d171449cb675b48838b955ddd0ba41a783dba1 Mon Sep 17 00:00:00 2001
Message-ID: <96d171449cb675b48838b955ddd0ba41a783dba1.1772815314.git.jdenemar@redhat.com>
From: Pavel Hrdina <phrdina@redhat.com>
Date: Thu, 26 Feb 2026 10:18:23 +0100
Subject: [PATCH] domain_conf: initialize network hostdev private data
Currently virDomainNetDef and virDomainActualNetDef use
virDomainHostdevDef directly as structure and the code doesn't call
virDomainHostdevDefNew() that would initialize private data.
This is hackish quick fix to solve a crash that happens in two
scenarios:
1. attaching any interface with hostdev backend
0x0000fffbfc0e2a90 in qemuDomainAttachHostPCIDevice (driver=0xfffbb4006750, vm=0xfffbf001f790, hostdev=0xfffbf400b150) at ../src/qemu/qemu_hotplug.c:1652
1652 if ((ret = qemuFDPassDirectTransferMonitor(hostdevPriv->vfioDeviceFd, priv->mon)) < 0)
2. starting VM with interface with hostdev backend using iommufd
0x00007f6638d5b9ca in qemuProcessOpenVfioDeviceFd (hostdev=hostdev@entry=0x7f6634425ee0) at ../src/qemu/qemu_process.c:7719
7719 hostdevPriv->vfioDeviceFd = qemuFDPassDirectNew(name, &vfioDeviceFd);
Proper fix for this issue is to refactor network code to use pointer and to
use virDomainHostdevDefNew().
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
Reviewed-by: Peter Krempa <pkrempa@redhat.com>
(cherry picked from commit fe782ed334ea0d4373e6dad093f5815fc925a56b)
https://issues.redhat.com/browse/RHEL-151916
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
---
src/conf/domain_conf.c | 23 +++++++++++++++++++++--
1 file changed, 21 insertions(+), 2 deletions(-)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 16ea9f0b2e..8877aefb7c 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -3489,6 +3489,20 @@ void virDomainVideoDefFree(virDomainVideoDef *def)
}
+static int
+virDomainHostdevDefPrivateDataNew(virDomainHostdevDef *def,
+ virDomainXMLOption *xmlopt)
+{
+ if (!xmlopt || !xmlopt->privateData.hostdevNew)
+ return 0;
+
+ if (!(def->privateData = xmlopt->privateData.hostdevNew()))
+ return -1;
+
+ return 0;
+}
+
+
virDomainHostdevDef *
virDomainHostdevDefNew(virDomainXMLOption *xmlopt)
{
@@ -3498,8 +3512,7 @@ virDomainHostdevDefNew(virDomainXMLOption *xmlopt)
def->info = g_new0(virDomainDeviceInfo, 1);
- if (xmlopt && xmlopt->privateData.hostdevNew &&
- !(def->privateData = xmlopt->privateData.hostdevNew())) {
+ if (virDomainHostdevDefPrivateDataNew(def, xmlopt) < 0) {
VIR_FREE(def->info);
VIR_FREE(def);
return NULL;
@@ -9675,6 +9688,9 @@ virDomainActualNetDefParseXML(xmlNodePtr node,
virDomainHostdevDef *hostdev = &actual->data.hostdev.def;
int type;
+ if (virDomainHostdevDefPrivateDataNew(hostdev, xmlopt) < 0)
+ goto error;
+
hostdev->parentnet = parent;
hostdev->info = &parent->info;
/* The helper function expects type to already be found and
@@ -10368,6 +10384,9 @@ virDomainNetDefParseXML(virDomainXMLOption *xmlopt,
g_autofree char *addrtype = virXPathString("string(./source/address/@type)", ctxt);
int type;
+ if (virDomainHostdevDefPrivateDataNew(&def->data.hostdev.def, xmlopt) < 0)
+ return NULL;
+
def->data.hostdev.def.parentnet = def;
def->data.hostdev.def.info = &def->info;
def->data.hostdev.def.mode = VIR_DOMAIN_HOSTDEV_MODE_SUBSYS;
--
2.53.0

View File

@ -0,0 +1,165 @@
From 33766fc329d60ba7fcf467756a442dd83cc00987 Mon Sep 17 00:00:00 2001
Message-ID: <33766fc329d60ba7fcf467756a442dd83cc00987.1772815312.git.jdenemar@redhat.com>
From: Andrea Bolognani <abologna@redhat.com>
Date: Fri, 5 Dec 2025 18:34:38 +0100
Subject: [PATCH] domain_validate: Reject NVRAM with read/write firmware
The combination doesn't make sense.
After this change the firmware-manual-bios-rw test cases starts
failing, as it should have in the first place.
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit 46970217a8258538b5dd9d746ec4191ee6d48d98)
https://issues.redhat.com/browse/RHEL-82645
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
---
src/conf/domain_validate.c | 14 +++++++
...are-manual-efi-rw-nvram.x86_64-latest.args | 37 -----------------
...ware-manual-efi-rw-nvram.x86_64-latest.err | 1 +
...ware-manual-efi-rw-nvram.x86_64-latest.xml | 40 -------------------
tests/qemuxmlconftest.c | 2 +-
5 files changed, 16 insertions(+), 78 deletions(-)
delete mode 100644 tests/qemuxmlconfdata/firmware-manual-efi-rw-nvram.x86_64-latest.args
create mode 100644 tests/qemuxmlconfdata/firmware-manual-efi-rw-nvram.x86_64-latest.err
delete mode 100644 tests/qemuxmlconfdata/firmware-manual-efi-rw-nvram.x86_64-latest.xml
diff --git a/src/conf/domain_validate.c b/src/conf/domain_validate.c
index 4558e7b210..09c1b3f13f 100644
--- a/src/conf/domain_validate.c
+++ b/src/conf/domain_validate.c
@@ -1765,6 +1765,20 @@ virDomainDefOSValidate(const virDomainDef *def,
}
}
+ if (loader->readonly == VIR_TRISTATE_BOOL_NO) {
+ if (loader->nvramTemplate) {
+ virReportError(VIR_ERR_XML_DETAIL, "%s",
+ _("NVRAM template is not permitted when loader is read/write"));
+ return -1;
+ }
+
+ if (loader->nvram) {
+ virReportError(VIR_ERR_XML_DETAIL, "%s",
+ _("NVRAM is not permitted when loader is read/write"));
+ return -1;
+ }
+ }
+
if (loader->stateless == VIR_TRISTATE_BOOL_YES) {
if (loader->nvramTemplate) {
virReportError(VIR_ERR_XML_DETAIL, "%s",
diff --git a/tests/qemuxmlconfdata/firmware-manual-efi-rw-nvram.x86_64-latest.args b/tests/qemuxmlconfdata/firmware-manual-efi-rw-nvram.x86_64-latest.args
deleted file mode 100644
index 6b3eec0a27..0000000000
--- a/tests/qemuxmlconfdata/firmware-manual-efi-rw-nvram.x86_64-latest.args
+++ /dev/null
@@ -1,37 +0,0 @@
-LC_ALL=C \
-PATH=/bin \
-HOME=/var/lib/libvirt/qemu/domain--1-guest \
-USER=test \
-LOGNAME=test \
-XDG_DATA_HOME=/var/lib/libvirt/qemu/domain--1-guest/.local/share \
-XDG_CACHE_HOME=/var/lib/libvirt/qemu/domain--1-guest/.cache \
-XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-guest/.config \
-/usr/bin/qemu-system-x86_64 \
--name guest=guest,debug-threads=on \
--S \
--object '{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/var/lib/libvirt/qemu/domain--1-guest/master-key.aes"}' \
--blockdev '{"driver":"file","filename":"/usr/share/edk2/ovmf/OVMF.combined.fd","node-name":"libvirt-pflash0-storage","auto-read-only":true,"discard":"unmap"}' \
--blockdev '{"node-name":"libvirt-pflash0-format","read-only":false,"driver":"raw","file":"libvirt-pflash0-storage"}' \
--blockdev '{"driver":"file","filename":"/path/to/guest_VARS.fd","node-name":"libvirt-pflash1-storage","read-only":false}' \
--machine pc-q35-10.0,usb=off,smm=on,dump-guest-core=off,memory-backend=pc.ram,pflash0=libvirt-pflash0-format,pflash1=libvirt-pflash1-storage,acpi=on \
--accel kvm \
--cpu qemu64 \
--global driver=cfi.pflash01,property=secure,value=on \
--m size=1048576k \
--object '{"qom-type":"memory-backend-ram","id":"pc.ram","size":1073741824}' \
--overcommit mem-lock=off \
--smp 1,sockets=1,cores=1,threads=1 \
--uuid 63840878-0deb-4095-97e6-fc444d9bc9fa \
--display none \
--no-user-config \
--nodefaults \
--chardev socket,id=charmonitor,fd=1729,server=on,wait=off \
--mon chardev=charmonitor,id=monitor,mode=control \
--rtc base=utc \
--no-shutdown \
--boot strict=on \
--audiodev '{"id":"audio1","driver":"none"}' \
--global ICH9-LPC.noreboot=off \
--watchdog-action reset \
--sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \
--msg timestamp=on
diff --git a/tests/qemuxmlconfdata/firmware-manual-efi-rw-nvram.x86_64-latest.err b/tests/qemuxmlconfdata/firmware-manual-efi-rw-nvram.x86_64-latest.err
new file mode 100644
index 0000000000..d0cf62061a
--- /dev/null
+++ b/tests/qemuxmlconfdata/firmware-manual-efi-rw-nvram.x86_64-latest.err
@@ -0,0 +1 @@
+NVRAM is not permitted when loader is read/write
diff --git a/tests/qemuxmlconfdata/firmware-manual-efi-rw-nvram.x86_64-latest.xml b/tests/qemuxmlconfdata/firmware-manual-efi-rw-nvram.x86_64-latest.xml
deleted file mode 100644
index f6436df80f..0000000000
--- a/tests/qemuxmlconfdata/firmware-manual-efi-rw-nvram.x86_64-latest.xml
+++ /dev/null
@@ -1,40 +0,0 @@
-<domain type='kvm'>
- <name>guest</name>
- <uuid>63840878-0deb-4095-97e6-fc444d9bc9fa</uuid>
- <memory unit='KiB'>1048576</memory>
- <currentMemory unit='KiB'>1048576</currentMemory>
- <vcpu placement='static'>1</vcpu>
- <os firmware='efi'>
- <type arch='x86_64' machine='pc-q35-10.0'>hvm</type>
- <firmware>
- <feature enabled='yes' name='secure-boot'/>
- </firmware>
- <loader readonly='no' secure='yes' type='pflash' format='raw'>/usr/share/edk2/ovmf/OVMF.combined.fd</loader>
- <nvram format='raw'>/path/to/guest_VARS.fd</nvram>
- <boot dev='hd'/>
- </os>
- <features>
- <acpi/>
- <smm state='on'/>
- </features>
- <cpu mode='custom' match='exact' check='none'>
- <model fallback='forbid'>qemu64</model>
- </cpu>
- <clock offset='utc'/>
- <on_poweroff>destroy</on_poweroff>
- <on_reboot>restart</on_reboot>
- <on_crash>destroy</on_crash>
- <devices>
- <emulator>/usr/bin/qemu-system-x86_64</emulator>
- <controller type='usb' index='0' model='none'/>
- <controller type='sata' index='0'>
- <address type='pci' domain='0x0000' bus='0x00' slot='0x1f' function='0x2'/>
- </controller>
- <controller type='pci' index='0' model='pcie-root'/>
- <input type='mouse' bus='ps2'/>
- <input type='keyboard' bus='ps2'/>
- <audio id='1' type='none'/>
- <watchdog model='itco' action='reset'/>
- <memballoon model='none'/>
- </devices>
-</domain>
diff --git a/tests/qemuxmlconftest.c b/tests/qemuxmlconftest.c
index 726281a4ab..5299f341cf 100644
--- a/tests/qemuxmlconftest.c
+++ b/tests/qemuxmlconftest.c
@@ -1583,7 +1583,7 @@ mymain(void)
DO_TEST_CAPS_LATEST("firmware-manual-efi-rw-legacy-paths");
DO_TEST_CAPS_LATEST("firmware-manual-efi-rw-modern-paths");
DO_TEST_CAPS_LATEST("firmware-manual-efi-rw-implicit");
- DO_TEST_CAPS_LATEST("firmware-manual-efi-rw-nvram");
+ DO_TEST_CAPS_LATEST_PARSE_ERROR("firmware-manual-efi-rw-nvram");
DO_TEST_CAPS_LATEST("firmware-manual-efi-loader-secure");
DO_TEST_CAPS_LATEST_PARSE_ERROR("firmware-manual-efi-loader-no-path");
DO_TEST_CAPS_LATEST("firmware-manual-efi-loader-path-nonstandard");
--
2.53.0

View File

@ -0,0 +1,157 @@
From 247090edf75839e13a23885a84cf090fbdd42228 Mon Sep 17 00:00:00 2001
Message-ID: <247090edf75839e13a23885a84cf090fbdd42228.1772815312.git.jdenemar@redhat.com>
From: Andrea Bolognani <abologna@redhat.com>
Date: Fri, 19 Dec 2025 15:19:26 +0100
Subject: [PATCH] domain_validate: Reject ROMs with format other than raw
The combination doesn't make sense.
After this change the firmware-auto-efi-format-loader-qcow2-rom
test case starts failing, as it should have in the first place.
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit c74adb33e4d97202e08a53119f463c54370e5816)
https://issues.redhat.com/browse/RHEL-82645
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
---
src/conf/domain_validate.c | 10 +++++
...format-loader-qcow2-rom.x86_64-latest.args | 34 ----------------
...-format-loader-qcow2-rom.x86_64-latest.err | 1 +
...-format-loader-qcow2-rom.x86_64-latest.xml | 39 -------------------
tests/qemuxmlconftest.c | 2 +-
5 files changed, 12 insertions(+), 74 deletions(-)
delete mode 100644 tests/qemuxmlconfdata/firmware-auto-efi-format-loader-qcow2-rom.x86_64-latest.args
create mode 100644 tests/qemuxmlconfdata/firmware-auto-efi-format-loader-qcow2-rom.x86_64-latest.err
delete mode 100644 tests/qemuxmlconfdata/firmware-auto-efi-format-loader-qcow2-rom.x86_64-latest.xml
diff --git a/src/conf/domain_validate.c b/src/conf/domain_validate.c
index 93a54f8cc7..7346a61731 100644
--- a/src/conf/domain_validate.c
+++ b/src/conf/domain_validate.c
@@ -1811,6 +1811,16 @@ virDomainDefOSValidate(const virDomainDef *def,
}
}
+ if (loader->type == VIR_DOMAIN_LOADER_TYPE_ROM) {
+ if (loader->format &&
+ loader->format != VIR_STORAGE_FILE_RAW) {
+ virReportError(VIR_ERR_XML_DETAIL,
+ _("Invalid format '%1$s' for ROM loader type"),
+ virStorageFileFormatTypeToString(loader->format));
+ return -1;
+ }
+ }
+
if (def->os.shim && !def->os.kernel) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("shim only allowed with kernel option"));
diff --git a/tests/qemuxmlconfdata/firmware-auto-efi-format-loader-qcow2-rom.x86_64-latest.args b/tests/qemuxmlconfdata/firmware-auto-efi-format-loader-qcow2-rom.x86_64-latest.args
deleted file mode 100644
index 417084d45e..0000000000
--- a/tests/qemuxmlconfdata/firmware-auto-efi-format-loader-qcow2-rom.x86_64-latest.args
+++ /dev/null
@@ -1,34 +0,0 @@
-LC_ALL=C \
-PATH=/bin \
-HOME=/var/lib/libvirt/qemu/domain--1-guest \
-USER=test \
-LOGNAME=test \
-XDG_DATA_HOME=/var/lib/libvirt/qemu/domain--1-guest/.local/share \
-XDG_CACHE_HOME=/var/lib/libvirt/qemu/domain--1-guest/.cache \
-XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-guest/.config \
-/usr/bin/qemu-system-x86_64 \
--name guest=guest,debug-threads=on \
--S \
--object '{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/var/lib/libvirt/qemu/domain--1-guest/master-key.aes"}' \
--machine pc-q35-10.0,usb=off,dump-guest-core=off,memory-backend=pc.ram,acpi=on \
--accel kvm \
--cpu qemu64 \
--bios /usr/share/edk2/ovmf/OVMF.inteltdx.secboot.fd \
--m size=1048576k \
--object '{"qom-type":"memory-backend-ram","id":"pc.ram","size":1073741824}' \
--overcommit mem-lock=off \
--smp 1,sockets=1,cores=1,threads=1 \
--uuid 63840878-0deb-4095-97e6-fc444d9bc9fa \
--display none \
--no-user-config \
--nodefaults \
--chardev socket,id=charmonitor,fd=1729,server=on,wait=off \
--mon chardev=charmonitor,id=monitor,mode=control \
--rtc base=utc \
--no-shutdown \
--boot strict=on \
--audiodev '{"id":"audio1","driver":"none"}' \
--global ICH9-LPC.noreboot=off \
--watchdog-action reset \
--sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \
--msg timestamp=on
diff --git a/tests/qemuxmlconfdata/firmware-auto-efi-format-loader-qcow2-rom.x86_64-latest.err b/tests/qemuxmlconfdata/firmware-auto-efi-format-loader-qcow2-rom.x86_64-latest.err
new file mode 100644
index 0000000000..b7b1400f6a
--- /dev/null
+++ b/tests/qemuxmlconfdata/firmware-auto-efi-format-loader-qcow2-rom.x86_64-latest.err
@@ -0,0 +1 @@
+Invalid format 'qcow2' for ROM loader type
diff --git a/tests/qemuxmlconfdata/firmware-auto-efi-format-loader-qcow2-rom.x86_64-latest.xml b/tests/qemuxmlconfdata/firmware-auto-efi-format-loader-qcow2-rom.x86_64-latest.xml
deleted file mode 100644
index 862a50ddb4..0000000000
--- a/tests/qemuxmlconfdata/firmware-auto-efi-format-loader-qcow2-rom.x86_64-latest.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<domain type='kvm'>
- <name>guest</name>
- <uuid>63840878-0deb-4095-97e6-fc444d9bc9fa</uuid>
- <memory unit='KiB'>1048576</memory>
- <currentMemory unit='KiB'>1048576</currentMemory>
- <vcpu placement='static'>1</vcpu>
- <os firmware='efi'>
- <type arch='x86_64' machine='pc-q35-10.0'>hvm</type>
- <firmware>
- <feature enabled='yes' name='enrolled-keys'/>
- <feature enabled='yes' name='secure-boot'/>
- </firmware>
- <loader type='rom' format='qcow2'>/usr/share/edk2/ovmf/OVMF.inteltdx.secboot.fd</loader>
- <boot dev='hd'/>
- </os>
- <features>
- <acpi/>
- </features>
- <cpu mode='custom' match='exact' check='none'>
- <model fallback='forbid'>qemu64</model>
- </cpu>
- <clock offset='utc'/>
- <on_poweroff>destroy</on_poweroff>
- <on_reboot>restart</on_reboot>
- <on_crash>destroy</on_crash>
- <devices>
- <emulator>/usr/bin/qemu-system-x86_64</emulator>
- <controller type='usb' index='0' model='none'/>
- <controller type='sata' index='0'>
- <address type='pci' domain='0x0000' bus='0x00' slot='0x1f' function='0x2'/>
- </controller>
- <controller type='pci' index='0' model='pcie-root'/>
- <input type='mouse' bus='ps2'/>
- <input type='keyboard' bus='ps2'/>
- <audio id='1' type='none'/>
- <watchdog model='itco' action='reset'/>
- <memballoon model='none'/>
- </devices>
-</domain>
diff --git a/tests/qemuxmlconftest.c b/tests/qemuxmlconftest.c
index 0a4dab9fe0..3296f6f990 100644
--- a/tests/qemuxmlconftest.c
+++ b/tests/qemuxmlconftest.c
@@ -1650,7 +1650,7 @@ mymain(void)
DO_TEST_CAPS_LATEST("firmware-auto-efi-nvram-network-iscsi");
DO_TEST_CAPS_LATEST("firmware-auto-efi-format-loader-qcow2");
- DO_TEST_CAPS_LATEST("firmware-auto-efi-format-loader-qcow2-rom");
+ DO_TEST_CAPS_LATEST_PARSE_ERROR("firmware-auto-efi-format-loader-qcow2-rom");
DO_TEST_CAPS_LATEST("firmware-auto-efi-format-loader-qcow2-nvram-path");
DO_TEST_CAPS_LATEST("firmware-auto-efi-format-nvram-qcow2");
DO_TEST_CAPS_LATEST("firmware-auto-efi-format-nvram-qcow2-path");
--
2.53.0

View File

@ -0,0 +1,140 @@
From 3872c63fb5af9e6d37f14b157171ab9fead24b83 Mon Sep 17 00:00:00 2001
Message-ID: <3872c63fb5af9e6d37f14b157171ab9fead24b83.1772815312.git.jdenemar@redhat.com>
From: Andrea Bolognani <abologna@redhat.com>
Date: Fri, 12 Dec 2025 16:31:09 +0100
Subject: [PATCH] domain_validate: Reject read/write ROMs
The combination doesn't make sense.
After this change the firmware-manual-bios-rw test case starts
failing, as it should have in the first place.
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit a5ae34aa74647e06114d85601c146a991323284b)
https://issues.redhat.com/browse/RHEL-82645
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
---
src/conf/domain_validate.c | 6 ++++
...firmware-manual-bios-rw.x86_64-latest.args | 32 -------------------
.../firmware-manual-bios-rw.x86_64-latest.err | 1 +
.../firmware-manual-bios-rw.x86_64-latest.xml | 28 ----------------
tests/qemuxmlconftest.c | 2 +-
5 files changed, 8 insertions(+), 61 deletions(-)
delete mode 100644 tests/qemuxmlconfdata/firmware-manual-bios-rw.x86_64-latest.args
create mode 100644 tests/qemuxmlconfdata/firmware-manual-bios-rw.x86_64-latest.err
delete mode 100644 tests/qemuxmlconfdata/firmware-manual-bios-rw.x86_64-latest.xml
diff --git a/src/conf/domain_validate.c b/src/conf/domain_validate.c
index 09c1b3f13f..93a54f8cc7 100644
--- a/src/conf/domain_validate.c
+++ b/src/conf/domain_validate.c
@@ -1766,6 +1766,12 @@ virDomainDefOSValidate(const virDomainDef *def,
}
if (loader->readonly == VIR_TRISTATE_BOOL_NO) {
+ if (loader->type == VIR_DOMAIN_LOADER_TYPE_ROM) {
+ virReportError(VIR_ERR_XML_DETAIL, "%s",
+ _("ROM loader type cannot be used as read/write"));
+ return -1;
+ }
+
if (loader->nvramTemplate) {
virReportError(VIR_ERR_XML_DETAIL, "%s",
_("NVRAM template is not permitted when loader is read/write"));
diff --git a/tests/qemuxmlconfdata/firmware-manual-bios-rw.x86_64-latest.args b/tests/qemuxmlconfdata/firmware-manual-bios-rw.x86_64-latest.args
deleted file mode 100644
index 969c7ad68c..0000000000
--- a/tests/qemuxmlconfdata/firmware-manual-bios-rw.x86_64-latest.args
+++ /dev/null
@@ -1,32 +0,0 @@
-LC_ALL=C \
-PATH=/bin \
-HOME=/var/lib/libvirt/qemu/domain--1-guest \
-USER=test \
-LOGNAME=test \
-XDG_DATA_HOME=/var/lib/libvirt/qemu/domain--1-guest/.local/share \
-XDG_CACHE_HOME=/var/lib/libvirt/qemu/domain--1-guest/.cache \
-XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-guest/.config \
-/usr/bin/qemu-system-x86_64 \
--name guest=guest,debug-threads=on \
--S \
--object '{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/var/lib/libvirt/qemu/domain--1-guest/master-key.aes"}' \
--machine pc-i440fx-10.0,usb=off,dump-guest-core=off,memory-backend=pc.ram,acpi=off \
--accel tcg \
--cpu qemu64 \
--bios /usr/share/seabios/bios.bin \
--m size=1048576k \
--object '{"qom-type":"memory-backend-ram","id":"pc.ram","size":1073741824}' \
--overcommit mem-lock=off \
--smp 1,sockets=1,cores=1,threads=1 \
--uuid 63840878-0deb-4095-97e6-fc444d9bc9fa \
--display none \
--no-user-config \
--nodefaults \
--chardev socket,id=charmonitor,fd=1729,server=on,wait=off \
--mon chardev=charmonitor,id=monitor,mode=control \
--rtc base=utc \
--no-shutdown \
--boot strict=on \
--audiodev '{"id":"audio1","driver":"none"}' \
--sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \
--msg timestamp=on
diff --git a/tests/qemuxmlconfdata/firmware-manual-bios-rw.x86_64-latest.err b/tests/qemuxmlconfdata/firmware-manual-bios-rw.x86_64-latest.err
new file mode 100644
index 0000000000..13e9d7c0f1
--- /dev/null
+++ b/tests/qemuxmlconfdata/firmware-manual-bios-rw.x86_64-latest.err
@@ -0,0 +1 @@
+ROM loader type cannot be used as read/write
diff --git a/tests/qemuxmlconfdata/firmware-manual-bios-rw.x86_64-latest.xml b/tests/qemuxmlconfdata/firmware-manual-bios-rw.x86_64-latest.xml
deleted file mode 100644
index 65bb8493c9..0000000000
--- a/tests/qemuxmlconfdata/firmware-manual-bios-rw.x86_64-latest.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<domain type='qemu'>
- <name>guest</name>
- <uuid>63840878-0deb-4095-97e6-fc444d9bc9fa</uuid>
- <memory unit='KiB'>1048576</memory>
- <currentMemory unit='KiB'>1048576</currentMemory>
- <vcpu placement='static'>1</vcpu>
- <os>
- <type arch='x86_64' machine='pc-i440fx-10.0'>hvm</type>
- <loader readonly='no' type='rom' format='raw'>/usr/share/seabios/bios.bin</loader>
- <boot dev='hd'/>
- </os>
- <cpu mode='custom' match='exact' check='none'>
- <model fallback='forbid'>qemu64</model>
- </cpu>
- <clock offset='utc'/>
- <on_poweroff>destroy</on_poweroff>
- <on_reboot>restart</on_reboot>
- <on_crash>destroy</on_crash>
- <devices>
- <emulator>/usr/bin/qemu-system-x86_64</emulator>
- <controller type='usb' index='0' model='none'/>
- <controller type='pci' index='0' model='pci-root'/>
- <input type='mouse' bus='ps2'/>
- <input type='keyboard' bus='ps2'/>
- <audio id='1' type='none'/>
- <memballoon model='none'/>
- </devices>
-</domain>
diff --git a/tests/qemuxmlconftest.c b/tests/qemuxmlconftest.c
index ba33267d4e..a45487b1b5 100644
--- a/tests/qemuxmlconftest.c
+++ b/tests/qemuxmlconftest.c
@@ -1576,7 +1576,7 @@ mymain(void)
DO_TEST_CAPS_LATEST("firmware-manual-bios");
DO_TEST_CAPS_LATEST("firmware-manual-bios-stateless");
DO_TEST_CAPS_LATEST_PARSE_ERROR("firmware-manual-bios-not-stateless");
- DO_TEST_CAPS_LATEST("firmware-manual-bios-rw");
+ DO_TEST_CAPS_LATEST_PARSE_ERROR("firmware-manual-bios-rw");
DO_TEST_CAPS_LATEST("firmware-manual-efi");
DO_TEST_CAPS_LATEST("firmware-manual-efi-features");
DO_TEST_CAPS_LATEST_ABI_UPDATE_PARSE_ERROR("firmware-manual-efi-features");
--
2.53.0

View File

@ -0,0 +1,119 @@
From 95ff5dcad20269f8e26eda628c85168dd4702285 Mon Sep 17 00:00:00 2001
Message-ID: <95ff5dcad20269f8e26eda628c85168dd4702285.1769699749.git.jdenemar@redhat.com>
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Mon, 26 Jan 2026 10:47:01 +0000
Subject: [PATCH] esx: Abstract all URL-creation code into one function
Abstract the places where we create URLs into one place. This is just
refactoring and should not change the behaviour.
Signed-off-by: Richard W.M. Jones <rjones@redhat.com>
(cherry picked from commit e013d5b5cae732ddeae479098165b9331b8ea441)
Resolves: https://issues.redhat.com/browse/RHEL-138300
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
---
src/esx/esx_driver.c | 53 +++++++++++++++++++++++++++++++++++---------
1 file changed, 43 insertions(+), 10 deletions(-)
diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c
index 9f965811b1..29735e359f 100644
--- a/src/esx/esx_driver.c
+++ b/src/esx/esx_driver.c
@@ -582,7 +582,37 @@ esxCapsInit(esxPrivate *priv)
return NULL;
}
+static char *
+esxCreateURL(const char *transport,
+ const char *server,
+ int port,
+ const char *path)
+{
+ char *url;
+ url = g_strdup_printf("%s://%s:%d%s",
+ transport,
+ server,
+ port,
+ path);
+ return url;
+}
+
+/*
+ * Same as above, but add it to a buffer because the calling code will
+ * append query strings etc.
+ */
+static void
+esxCreateURLBuffer(virBuffer *buffer,
+ const char *transport,
+ const char *server,
+ int port,
+ const char *path)
+{
+ g_autofree char *url = esxCreateURL(transport, server, port, path);
+
+ virBufferAdd(buffer, url, -1);
+}
static int
esxConnectToHost(esxPrivate *priv,
@@ -619,8 +649,8 @@ esxConnectToHost(esxPrivate *priv,
conn->uri->server)))
goto cleanup;
- url = g_strdup_printf("%s://%s:%d/sdk", priv->parsedUri->transport,
- conn->uri->server, conn->uri->port);
+ url = esxCreateURL(priv->parsedUri->transport,
+ conn->uri->server, conn->uri->port, "/sdk");
if (esxVI_Context_Alloc(&priv->host) < 0 ||
esxVI_Context_Connect(priv->host, url, ipAddress, username, password,
@@ -706,8 +736,8 @@ esxConnectToVCenter(esxPrivate *priv,
if (!(password = virAuthGetPassword(conn, auth, "esx", username, hostname)))
return -1;
- url = g_strdup_printf("%s://%s:%d/sdk", priv->parsedUri->transport, hostname,
- conn->uri->port);
+ url = esxCreateURL(priv->parsedUri->transport, hostname,
+ conn->uri->port, "/sdk");
if (esxVI_Context_Alloc(&priv->vCenter) < 0 ||
esxVI_Context_Connect(priv->vCenter, url, ipAddress, username,
@@ -2357,8 +2387,9 @@ esxDomainScreenshot(virDomainPtr domain, virStreamPtr stream,
}
/* Build URL */
- virBufferAsprintf(&buffer, "%s://%s:%d/screen?id=", priv->parsedUri->transport,
- domain->conn->uri->server, domain->conn->uri->port);
+ esxCreateURLBuffer(&buffer, priv->parsedUri->transport,
+ domain->conn->uri->server, domain->conn->uri->port,
+ "/screen?id=");
virBufferURIEncodeString(&buffer, virtualMachine->obj->value);
url = virBufferContentAndReset(&buffer);
@@ -2563,8 +2594,9 @@ esxDomainGetXMLDesc(virDomainPtr domain, unsigned int flags)
goto cleanup;
}
- virBufferAsprintf(&buffer, "%s://%s:%d/folder/", priv->parsedUri->transport,
- domain->conn->uri->server, domain->conn->uri->port);
+ esxCreateURLBuffer(&buffer, priv->parsedUri->transport,
+ domain->conn->uri->server, domain->conn->uri->port,
+ "/folder/");
virBufferURIEncodeString(&buffer, directoryAndFileName);
virBufferAddLit(&buffer, "?dcPath=");
virBufferURIEncodeString(&buffer, priv->primary->datacenterPath);
@@ -2987,8 +3019,9 @@ esxDomainDefineXMLFlags(virConnectPtr conn, const char *xml, unsigned int flags)
goto cleanup;
}
- virBufferAsprintf(&buffer, "%s://%s:%d/folder/", priv->parsedUri->transport,
- conn->uri->server, conn->uri->port);
+ esxCreateURLBuffer(&buffer, priv->parsedUri->transport,
+ conn->uri->server, conn->uri->port,
+ "/folder/");
if (directoryName) {
virBufferURIEncodeString(&buffer, directoryName);
--
2.52.0

View File

@ -0,0 +1,43 @@
From 16276aad5c682651e2a5aabe7d5a7258dda251c1 Mon Sep 17 00:00:00 2001
Message-ID: <16276aad5c682651e2a5aabe7d5a7258dda251c1.1769173967.git.jdenemar@redhat.com>
From: Michal Privoznik <mprivozn@redhat.com>
Date: Tue, 20 Jan 2026 10:08:29 +0100
Subject: [PATCH] esx: Allow connecting to IPv6 server
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
When connecting to a VMWare server, the hostname from URI is
resolved using esxUtil_ResolveHostname() which in turn calls
getaddrinfo(). But in the hints argument, we restrict the return
address to be IPv4 (AF_INET) which obviously fails if the address
to resolve is an IPv6 address. Set the hint to AF_UNSPEC which
allows both IPv4 and IPv6. While at it, also allow IPv4 addresses
mapped in IPv6 by setting AI_V4MAPPED flag.
Resolves: https://issues.redhat.com/browse/RHEL-138300
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
(cherry picked from commit 845210011a9ffd9d17e30c51cbc81ba67c5d3166)
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
---
src/esx/esx_util.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/esx/esx_util.c b/src/esx/esx_util.c
index 7ee0e5f7c0..12a34a2275 100644
--- a/src/esx/esx_util.c
+++ b/src/esx/esx_util.c
@@ -280,8 +280,8 @@ esxUtil_ResolveHostname(const char *hostname, char **ipAddress)
int errcode;
g_autofree char *address = NULL;
- hints.ai_flags = AI_ADDRCONFIG;
- hints.ai_family = AF_INET;
+ hints.ai_flags = AI_ADDRCONFIG | AI_V4MAPPED;
+ hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = 0;
--
2.52.0

View File

@ -0,0 +1,29 @@
From 0e5f062ba33929bc592fff175a2cd9d043a32b23 Mon Sep 17 00:00:00 2001
Message-ID: <0e5f062ba33929bc592fff175a2cd9d043a32b23.1769699749.git.jdenemar@redhat.com>
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Mon, 26 Jan 2026 10:38:02 +0000
Subject: [PATCH] esx: Debug URL just before opening with curl
Signed-off-by: Richard W.M. Jones <rjones@redhat.com>
(cherry picked from commit 38c952d89317f5b4bd23223f9a9d8be086ef7a40)
Resolves: https://issues.redhat.com/browse/RHEL-138300
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
---
src/esx/esx_vi.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/esx/esx_vi.c b/src/esx/esx_vi.c
index 3264afc13a..8d2ffb3f8f 100644
--- a/src/esx/esx_vi.c
+++ b/src/esx/esx_vi.c
@@ -231,6 +231,8 @@ esxVI_CURL_Perform(esxVI_CURL *curl, const char *url)
long responseCode = 0;
const char *redirectUrl = NULL;
+ VIR_DEBUG("URL: %s", url);
+
errorCode = curl_easy_perform(curl->handle);
if (errorCode != CURLE_OK) {
--
2.52.0

View File

@ -0,0 +1,57 @@
From 1ac21634942d30288dd11005d1d832b8dda86ceb Mon Sep 17 00:00:00 2001
Message-ID: <1ac21634942d30288dd11005d1d832b8dda86ceb.1769699749.git.jdenemar@redhat.com>
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Mon, 26 Jan 2026 17:54:57 +0000
Subject: [PATCH] esx: Switch to creating URLs using virURIFormat
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Since libvirt has existing support for creating URIs, use that rather
than home-rolling our own code without any escaping.
As a side-effect this ensures that URLs containing IPv6 addresses are
escaped correctly, for example as below (note square brackets):
https://[1234:56:0:789a:bcde:72ff:fe0a:7baa]:443/sdk
Fixes: https://issues.redhat.com/browse/RHEL-138300
Updates: commit 845210011a9ffd9d17e30c51cbc81ba67c5d3166
Reported-by: Ming Xie <mxie@redhat.com>
Signed-off-by: Richard W.M. Jones <rjones@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
(cherry picked from commit 13889feb14a24fdf7717960aa5331a0b63ce97ed)
Resolves: https://issues.redhat.com/browse/RHEL-138300
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
---
src/esx/esx_driver.c | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c
index 29735e359f..40b7f793cd 100644
--- a/src/esx/esx_driver.c
+++ b/src/esx/esx_driver.c
@@ -588,14 +588,14 @@ esxCreateURL(const char *transport,
int port,
const char *path)
{
- char *url;
+ virURI uri = {
+ .scheme = (char*)transport,
+ .server = (char*)server,
+ .port = port,
+ .path = (char*)path,
+ };
- url = g_strdup_printf("%s://%s:%d%s",
- transport,
- server,
- port,
- path);
- return url;
+ return virURIFormat(&uri);
}
/*
--
2.52.0

View File

@ -0,0 +1,60 @@
From 1ff41e00c1d0a280b22ba4f8bf4e86472570486a Mon Sep 17 00:00:00 2001
Message-ID: <1ff41e00c1d0a280b22ba4f8bf4e86472570486a.1769699749.git.jdenemar@redhat.com>
From: Michal Privoznik <mprivozn@redhat.com>
Date: Tue, 6 Jan 2026 17:18:03 +0100
Subject: [PATCH] esx: URI encode inventory objects twice
While discouraged by a KB article to use special characters in
inventory object names [1], ESX won't stop you. And thus users
can end up with a datastore named "datastore2+", for instance.
The datastore name (and datacenter path) are important when
fetching/uploading a .vmx file (used in APIs like
virDomainGetXMLDesc() or virDomainDefineXML()). And while we do
URI encode both (dcPath and dsName), encoding them once is not
enough. Cole Robinson discovered [2] that they need to be
URI-encoded twice. Use newly introduced
esxUtil_EscapeInventoryObject() helper to encode them twice.
1: https://knowledge.broadcom.com/external/article/386368/vcenter-inventory-object-name-with-speci.html
2: https://issues.redhat.com/browse/RHEL-133729#comment-28604072
Resolves: https://issues.redhat.com/browse/RHEL-134127
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
Reviewed-by: Richard W.M. Jones <rjones@redhat.com>
(cherry picked from commit 6c9d2591c668732eb05cf17d27c9102ef3d40b39)
Resolves: https://issues.redhat.com/browse/RHEL-140196
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
---
src/esx/esx_driver.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c
index 40b7f793cd..010c62b8e8 100644
--- a/src/esx/esx_driver.c
+++ b/src/esx/esx_driver.c
@@ -2599,9 +2599,9 @@ esxDomainGetXMLDesc(virDomainPtr domain, unsigned int flags)
"/folder/");
virBufferURIEncodeString(&buffer, directoryAndFileName);
virBufferAddLit(&buffer, "?dcPath=");
- virBufferURIEncodeString(&buffer, priv->primary->datacenterPath);
+ esxUtil_EscapeInventoryObject(&buffer, priv->primary->datacenterPath);
virBufferAddLit(&buffer, "&dsName=");
- virBufferURIEncodeString(&buffer, datastoreName);
+ esxUtil_EscapeInventoryObject(&buffer, datastoreName);
url = virBufferContentAndReset(&buffer);
@@ -3035,9 +3035,9 @@ esxDomainDefineXMLFlags(virConnectPtr conn, const char *xml, unsigned int flags)
virBufferURIEncodeString(&buffer, escapedName);
virBufferAddLit(&buffer, ".vmx?dcPath=");
- virBufferURIEncodeString(&buffer, priv->primary->datacenterPath);
+ esxUtil_EscapeInventoryObject(&buffer, priv->primary->datacenterPath);
virBufferAddLit(&buffer, "&dsName=");
- virBufferURIEncodeString(&buffer, datastoreName);
+ esxUtil_EscapeInventoryObject(&buffer, datastoreName);
url = virBufferContentAndReset(&buffer);
--
2.52.0

View File

@ -0,0 +1,76 @@
From 0776d3a966522785927456bf85037503a9d85bd7 Mon Sep 17 00:00:00 2001
Message-ID: <0776d3a966522785927456bf85037503a9d85bd7.1769699749.git.jdenemar@redhat.com>
From: Michal Privoznik <mprivozn@redhat.com>
Date: Wed, 7 Jan 2026 10:34:25 +0100
Subject: [PATCH] esx_util: Introduce esxUtil_EscapeInventoryObject()
The aim of this helper function is to URI-encode given string
twice. There's a bug (fixed in next commit) in which we're unable
to fetch .vmx file for a domain if corresponding datastore
contains some special characters (like +). Cole Robinson
discovered that encoding datastore twice enables libvirt to work
around the issue [2]. Well, this function does exactly that.
It was tested with the following inputs and all worked
flawlessly: "datastore", "datastore2", "datastore2+",
"datastore3+-@", "data store2+".
1: https://issues.redhat.com/browse/RHEL-134127
2: https://issues.redhat.com/browse/RHEL-133729#comment-28604072
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
Reviewed-by: Richard W.M. Jones <rjones@redhat.com>
(cherry picked from commit ffe74c7c551bd641cbcaa2512ed0ad4a25d3980b)
Resolves: https://issues.redhat.com/browse/RHEL-140196
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
---
src/esx/esx_util.c | 18 ++++++++++++++++++
src/esx/esx_util.h | 3 +++
2 files changed, 21 insertions(+)
diff --git a/src/esx/esx_util.c b/src/esx/esx_util.c
index 12a34a2275..963bcd0a75 100644
--- a/src/esx/esx_util.c
+++ b/src/esx/esx_util.c
@@ -448,3 +448,21 @@ esxUtil_EscapeForXml(const char *string)
return virBufferContentAndReset(&buffer);
}
+
+
+/* esxUtil_EscapeInventoryObject:
+ * @buf: the buffer to append to
+ * @string: the string argument which will be URI-encoded
+ *
+ * URI-encode given @string TWICE and append the result to the @buf. This is
+ * to be used with inventory objects (like 'dcPath' and 'dsName') to work
+ * around a VMware bug in which once round of URI-encoding is not enough.
+ */
+void
+esxUtil_EscapeInventoryObject(virBuffer *buf, const char *string)
+{
+ g_autoptr(GString) escaped = g_string_new(NULL);
+
+ g_string_append_uri_escaped(escaped, string, NULL, false);
+ virBufferURIEncodeString(buf, escaped->str);
+}
diff --git a/src/esx/esx_util.h b/src/esx/esx_util.h
index 58bc44e744..29f01e0c15 100644
--- a/src/esx/esx_util.h
+++ b/src/esx/esx_util.h
@@ -22,6 +22,7 @@
#pragma once
#include "internal.h"
+#include "virbuffer.h"
#include "viruri.h"
#define ESX_VI_CHECK_ARG_LIST(val) \
@@ -67,3 +68,5 @@ void esxUtil_ReplaceSpecialWindowsPathChars(char *string);
char *esxUtil_EscapeDatastoreItem(const char *string);
char *esxUtil_EscapeForXml(const char *string);
+
+void esxUtil_EscapeInventoryObject(virBuffer *buf, const char *string);
--
2.52.0

View File

@ -0,0 +1,69 @@
From af33f07936bd97081a626499700a872c9cfdbecb Mon Sep 17 00:00:00 2001
Message-ID: <af33f07936bd97081a626499700a872c9cfdbecb.1772815314.git.jdenemar@redhat.com>
From: Andrea Bolognani <abologna@redhat.com>
Date: Fri, 30 Jan 2026 18:34:40 +0100
Subject: [PATCH] include: Mention varstore where applicable
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
We are not introducing additional API flags for varstore
handling since that would require unnecessary churn in all
libvirt-based apps, and the intent is the same: recreate
the UEFI variable storage, be it NVRAM or varstore, from its
template.
In order to clarify that the existing flags affect varstore
too, update their documentation.
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
(cherry picked from commit 31e40b6229cd3bc1affaecdc577f1ec1dd85d54c)
https://issues.redhat.com/browse/RHEL-82645
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
---
include/libvirt/libvirt-domain-snapshot.h | 2 +-
include/libvirt/libvirt-domain.h | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/include/libvirt/libvirt-domain-snapshot.h b/include/libvirt/libvirt-domain-snapshot.h
index a11cd3f823..e14b661e37 100644
--- a/include/libvirt/libvirt-domain-snapshot.h
+++ b/include/libvirt/libvirt-domain-snapshot.h
@@ -217,7 +217,7 @@ typedef enum {
VIR_DOMAIN_SNAPSHOT_REVERT_RUNNING = 1 << 0, /* Run after revert (Since: 0.9.5) */
VIR_DOMAIN_SNAPSHOT_REVERT_PAUSED = 1 << 1, /* Pause after revert (Since: 0.9.5) */
VIR_DOMAIN_SNAPSHOT_REVERT_FORCE = 1 << 2, /* Allow risky reverts (Since: 0.9.7) */
- VIR_DOMAIN_SNAPSHOT_REVERT_RESET_NVRAM = 1 << 3, /* Re-initialize NVRAM from template (Since: 8.1.0) */
+ VIR_DOMAIN_SNAPSHOT_REVERT_RESET_NVRAM = 1 << 3, /* Re-initialize NVRAM/varstore from template (Since: 8.1.0) */
} virDomainSnapshotRevertFlags;
/* Revert the domain to a point-in-time snapshot. The
diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h
index 8e62bd23d4..221e22443e 100644
--- a/include/libvirt/libvirt-domain.h
+++ b/include/libvirt/libvirt-domain.h
@@ -371,7 +371,7 @@ typedef enum {
VIR_DOMAIN_START_BYPASS_CACHE = 1 << 2, /* Avoid file system cache pollution (Since: 0.9.4) */
VIR_DOMAIN_START_FORCE_BOOT = 1 << 3, /* Boot, discarding any managed save (Since: 0.9.5) */
VIR_DOMAIN_START_VALIDATE = 1 << 4, /* Validate the XML document against schema (Since: 1.2.12) */
- VIR_DOMAIN_START_RESET_NVRAM = 1 << 5, /* Re-initialize NVRAM from template (Since: 8.1.0) */
+ VIR_DOMAIN_START_RESET_NVRAM = 1 << 5, /* Re-initialize NVRAM/varstore from template (Since: 8.1.0) */
} virDomainCreateFlags;
@@ -1652,7 +1652,7 @@ typedef enum {
VIR_DOMAIN_SAVE_BYPASS_CACHE = 1 << 0, /* Avoid file system cache pollution (Since: 0.9.4) */
VIR_DOMAIN_SAVE_RUNNING = 1 << 1, /* Favor running over paused (Since: 0.9.5) */
VIR_DOMAIN_SAVE_PAUSED = 1 << 2, /* Favor paused over running (Since: 0.9.5) */
- VIR_DOMAIN_SAVE_RESET_NVRAM = 1 << 3, /* Re-initialize NVRAM from template (Since: 8.1.0) */
+ VIR_DOMAIN_SAVE_RESET_NVRAM = 1 << 3, /* Re-initialize NVRAM/varstore from template (Since: 8.1.0) */
} virDomainSaveRestoreFlags;
int virDomainSave (virDomainPtr domain,
--
2.53.0

View File

@ -0,0 +1,38 @@
From a07ea47ade888579a3ceb1699a2e029c699fda4f Mon Sep 17 00:00:00 2001
Message-ID: <a07ea47ade888579a3ceb1699a2e029c699fda4f.1771423659.git.jdenemar@redhat.com>
From: Pavel Hrdina <phrdina@redhat.com>
Date: Tue, 17 Feb 2026 08:38:07 +0100
Subject: [PATCH] iommufd: fix FD leak in case of error
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Reported-by: coverity
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
(cherry picked from commit f37e14119c257281eab4fd1fed1b1018fe4f63b1)
Resolves: https://issues.redhat.com/browse/RHEL-150351
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
---
src/util/viriommufd.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/src/util/viriommufd.c b/src/util/viriommufd.c
index 1f3353eab4..b62d59241d 100644
--- a/src/util/viriommufd.c
+++ b/src/util/viriommufd.c
@@ -87,8 +87,10 @@ virIOMMUFDOpenDevice(void)
if ((fd = open(VIR_IOMMU_DEV_PATH, O_RDWR | O_CLOEXEC)) < 0)
virReportSystemError(errno, "%s", _("cannot open IOMMUFD device"));
- if (virIOMMUFDSetRLimitMode(fd, true) < 0)
+ if (virIOMMUFDSetRLimitMode(fd, true) < 0) {
+ VIR_FORCE_CLOSE(fd);
return -1;
+ }
return fd;
}
--
2.53.0

View File

@ -0,0 +1,125 @@
From 48ae2b31930d1b5203c88acd6498893948aa2674 Mon Sep 17 00:00:00 2001
Message-ID: <48ae2b31930d1b5203c88acd6498893948aa2674.1771423659.git.jdenemar@redhat.com>
From: Pavel Hrdina <phrdina@redhat.com>
Date: Sun, 15 Feb 2026 19:42:39 +0100
Subject: [PATCH] qemu: Convert IOMMUFD to qemuFDPassDirect
This cleans up creating QEMU command line and makes it easier when
adding hotplug support.
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit df59beed37db5451a44955c1c440eebc474bffb2)
Resolves: https://issues.redhat.com/browse/RHEL-150351
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
---
src/qemu/qemu_command.c | 7 ++-----
src/qemu/qemu_domain.c | 4 ++--
src/qemu/qemu_domain.h | 2 +-
src/qemu/qemu_process.c | 6 ++++--
tests/qemuxmlconftest.c | 6 ++++--
5 files changed, 13 insertions(+), 12 deletions(-)
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 3119191413..443780eff5 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -5350,19 +5350,16 @@ qemuBuildIOMMUFDCommandLine(virCommand *cmd,
virDomainObj *vm)
{
qemuDomainObjPrivate *priv = vm->privateData;
- g_autofree char *fdstr = g_strdup_printf("%d", priv->iommufd);
g_autoptr(virJSONValue) props = NULL;
if (!virDomainDefHasPCIHostdevWithIOMMUFD(def))
return 0;
- virCommandPassFD(cmd, priv->iommufd, VIR_COMMAND_PASS_FD_CLOSE_PARENT);
-
- priv->iommufd = -1;
+ qemuFDPassDirectTransferCommand(priv->iommufd, cmd);
if (qemuMonitorCreateObjectProps(&props, "iommufd",
"iommufd0",
- "S:fd", fdstr,
+ "S:fd", qemuFDPassDirectGetPath(priv->iommufd),
NULL) < 0)
return -1;
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 64b01e524f..d9cd9324e0 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -1975,7 +1975,7 @@ qemuDomainObjPrivateDataClear(qemuDomainObjPrivate *priv)
priv->migrationRecoverSetup = false;
- VIR_FORCE_CLOSE(priv->iommufd);
+ g_clear_pointer(&priv->iommufd, qemuFDPassDirectFree);
g_clear_pointer(&priv->memoryBackingDir, g_free);
}
@@ -2044,7 +2044,7 @@ qemuDomainObjPrivateAlloc(void *opaque)
priv->blockjobs = virHashNew(virObjectUnref);
priv->fds = virHashNew(g_object_unref);
- priv->iommufd = -1;
+ priv->iommufd = NULL;
priv->pidMonitored = -1;
/* agent commands block by default, user can choose different behavior */
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
index 30ca67bf76..a5403ecc93 100644
--- a/src/qemu/qemu_domain.h
+++ b/src/qemu/qemu_domain.h
@@ -264,7 +264,7 @@ struct _qemuDomainObjPrivate {
/* named file descriptor groups associated with the VM */
GHashTable *fds;
- int iommufd;
+ qemuFDPassDirect *iommufd;
char *memoryBackingDir;
};
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 3729edcd7e..91167d73bc 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -7685,13 +7685,15 @@ static int
qemuProcessOpenIommuFd(virDomainObj *vm)
{
qemuDomainObjPrivate *priv = vm->privateData;
+ int iommufd;
VIR_DEBUG("Opening IOMMU FD for domain %s", vm->def->name);
- if ((priv->iommufd = virIOMMUFDOpenDevice()) < 0)
+ if ((iommufd = virIOMMUFDOpenDevice()) < 0)
return -1;
- VIR_DEBUG("Opened IOMMU FD %d for domain %s", priv->iommufd, vm->def->name);
+ priv->iommufd = qemuFDPassDirectNew("iommufd", &iommufd);
+
return 0;
}
diff --git a/tests/qemuxmlconftest.c b/tests/qemuxmlconftest.c
index 6f16b6cee8..b58bdc1f80 100644
--- a/tests/qemuxmlconftest.c
+++ b/tests/qemuxmlconftest.c
@@ -406,8 +406,10 @@ testQemuPrepareHostdev(virDomainObj *vm)
}
}
- if (virDomainDefHasPCIHostdevWithIOMMUFD(vm->def))
- priv->iommufd = 0;
+ if (virDomainDefHasPCIHostdevWithIOMMUFD(vm->def)) {
+ int iommufd = 0;
+ priv->iommufd = qemuFDPassDirectNew("iommufd", &iommufd);
+ }
}
--
2.53.0

View File

@ -0,0 +1,129 @@
From f0bc052ed97cd00f6d3da0493bb33b95db93a776 Mon Sep 17 00:00:00 2001
Message-ID: <f0bc052ed97cd00f6d3da0493bb33b95db93a776.1771423659.git.jdenemar@redhat.com>
From: Pavel Hrdina <phrdina@redhat.com>
Date: Sun, 15 Feb 2026 19:28:16 +0100
Subject: [PATCH] qemu: Convert vfioDeviceFd to qemuFDPassDirect
This cleans up creating QEMU command line and makes it easier when
adding hotplug support.
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit 4611f227c7882c8b9237da5e2fab21932ef6bd51)
Resolves: https://issues.redhat.com/browse/RHEL-150351
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
---
src/qemu/qemu_command.c | 15 +++++----------
src/qemu/qemu_domain.c | 4 ++--
src/qemu/qemu_domain.h | 2 +-
src/qemu/qemu_process.c | 6 +++++-
tests/qemuxmlconftest.c | 4 +++-
5 files changed, 16 insertions(+), 15 deletions(-)
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 443780eff5..33127fbc0a 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -4811,12 +4811,10 @@ qemuBuildPCIHostdevDevProps(const virDomainDef *def,
pcisrc->driver.iommufd == VIR_TRISTATE_BOOL_YES) {
qemuDomainHostdevPrivate *hostdevPriv = QEMU_DOMAIN_HOSTDEV_PRIVATE(dev);
- if (hostdevPriv->vfioDeviceFd != -1) {
- g_autofree char *fdstr = g_strdup_printf("%d", hostdevPriv->vfioDeviceFd);
- if (virJSONValueObjectAdd(&props, "S:fd", fdstr, NULL) < 0)
- return NULL;
- hostdevPriv->vfioDeviceFd = -1;
- }
+ if (virJSONValueObjectAdd(&props,
+ "S:fd", qemuFDPassDirectGetPath(hostdevPriv->vfioDeviceFd),
+ NULL) < 0)
+ return NULL;
}
if (qemuBuildDeviceAddressProps(props, def, dev->info) < 0)
@@ -5266,10 +5264,7 @@ qemuBuildHostdevCommandLine(virCommand *cmd,
if (subsys->u.pci.driver.iommufd == VIR_TRISTATE_BOOL_YES) {
qemuDomainHostdevPrivate *hostdevPriv = QEMU_DOMAIN_HOSTDEV_PRIVATE(hostdev);
- if (hostdevPriv->vfioDeviceFd != -1) {
- virCommandPassFD(cmd, hostdevPriv->vfioDeviceFd,
- VIR_COMMAND_PASS_FD_CLOSE_PARENT);
- }
+ qemuFDPassDirectTransferCommand(hostdevPriv->vfioDeviceFd, cmd);
}
if (!(devprops = qemuBuildPCIHostdevDevProps(def, hostdev)))
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index d9cd9324e0..ada9d3431c 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -1245,7 +1245,7 @@ qemuDomainHostdevPrivateDispose(void *obj)
{
qemuDomainHostdevPrivate *priv = obj;
- VIR_FORCE_CLOSE(priv->vfioDeviceFd);
+ g_clear_pointer(&priv->vfioDeviceFd, qemuFDPassDirectFree);
}
@@ -1271,7 +1271,7 @@ qemuDomainHostdevPrivateNew(void)
if (!(priv = virObjectNew(qemuDomainHostdevPrivateClass)))
return NULL;
- priv->vfioDeviceFd = -1;
+ priv->vfioDeviceFd = NULL;
return (virObject *) priv;
}
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
index a5403ecc93..8aa94fc25b 100644
--- a/src/qemu/qemu_domain.h
+++ b/src/qemu/qemu_domain.h
@@ -471,7 +471,7 @@ struct _qemuDomainHostdevPrivate {
virObject parent;
/* VFIO device file descriptor for iommufd passthrough */
- int vfioDeviceFd;
+ qemuFDPassDirect *vfioDeviceFd;
};
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 91167d73bc..59fff1aa19 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -7710,10 +7710,14 @@ qemuProcessOpenVfioDeviceFd(virDomainHostdevDef *hostdev)
{
qemuDomainHostdevPrivate *hostdevPriv = QEMU_DOMAIN_HOSTDEV_PRIVATE(hostdev);
virDomainHostdevSubsysPCI *pci = &hostdev->source.subsys.u.pci;
+ g_autofree char *name = g_strdup_printf("hostdev-%s-fd", hostdev->info->alias);
+ int vfioDeviceFd;
- if ((hostdevPriv->vfioDeviceFd = virPCIDeviceOpenVfioFd(&pci->addr)) < 0)
+ if ((vfioDeviceFd = virPCIDeviceOpenVfioFd(&pci->addr)) < 0)
return -1;
+ hostdevPriv->vfioDeviceFd = qemuFDPassDirectNew(name, &vfioDeviceFd);
+
return 0;
}
diff --git a/tests/qemuxmlconftest.c b/tests/qemuxmlconftest.c
index b58bdc1f80..bddd659fd4 100644
--- a/tests/qemuxmlconftest.c
+++ b/tests/qemuxmlconftest.c
@@ -357,8 +357,10 @@ testQemuPrepareHostdevPCI(virDomainHostdevDef *hostdev)
qemuDomainHostdevPrivate *hostdevPriv = QEMU_DOMAIN_HOSTDEV_PRIVATE(hostdev);
if (virHostdevIsPCIDeviceWithIOMMUFD(hostdev)) {
+ g_autofree char *name = g_strdup_printf("hostdev-%s-fd", hostdev->info->alias);
/* Use a placeholder FD value for tests */
- hostdevPriv->vfioDeviceFd = 0;
+ int vfioDeviceFD = 0;
+ hostdevPriv->vfioDeviceFd = qemuFDPassDirectNew(name, &vfioDeviceFD);
}
}
--
2.53.0

View File

@ -0,0 +1,118 @@
From ab8dbe11d56790f6fd140919559ad7610cc1f535 Mon Sep 17 00:00:00 2001
Message-ID: <ab8dbe11d56790f6fd140919559ad7610cc1f535.1772815314.git.jdenemar@redhat.com>
From: Andrea Bolognani <abologna@redhat.com>
Date: Fri, 23 Jan 2026 19:47:13 +0100
Subject: [PATCH] qemu: Create and delete varstore file
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Simply mimicking what is currently done for NVRAM files does
the trick. A few user-visible messages are updated to reflect
the fact that they apply both to NVRAM and varstore.
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
(cherry picked from commit 5dc97de2c4fb4c2097c29cbe0eb38e3cdb4e92b0)
https://issues.redhat.com/browse/RHEL-82645
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
---
src/qemu/qemu_driver.c | 14 +++++++++-----
src/qemu/qemu_process.c | 28 ++++++++++++++++++++++++++--
2 files changed, 35 insertions(+), 7 deletions(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index d314aa94ce..ad894c7584 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -6639,22 +6639,26 @@ qemuDomainUndefineFlags(virDomainPtr dom,
}
}
- if (vm->def->os.loader && vm->def->os.loader->nvram &&
- virStorageSourceIsLocalStorage(vm->def->os.loader->nvram)) {
- nvram_path = g_strdup(vm->def->os.loader->nvram->path);
+ if (vm->def->os.loader) {
+ if (vm->def->os.loader->nvram &&
+ virStorageSourceIsLocalStorage(vm->def->os.loader->nvram)) {
+ nvram_path = g_strdup(vm->def->os.loader->nvram->path);
+ } else if (vm->def->os.varstore && vm->def->os.varstore->path) {
+ nvram_path = g_strdup(vm->def->os.varstore->path);
+ }
}
if (nvram_path && virFileExists(nvram_path)) {
if ((flags & VIR_DOMAIN_UNDEFINE_NVRAM)) {
if (unlink(nvram_path) < 0) {
virReportSystemError(errno,
- _("failed to remove nvram: %1$s"),
+ _("Failed to remove NVRAM/varstore: %1$s"),
nvram_path);
goto endjob;
}
} else if (!(flags & VIR_DOMAIN_UNDEFINE_KEEP_NVRAM)) {
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
- _("cannot undefine domain with nvram"));
+ _("Cannot undefine domain with NVRAM/varstore"));
goto endjob;
}
}
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 47deb9abb9..3ca87df284 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -5031,6 +5031,27 @@ qemuPrepareNVRAM(virQEMUDriver *driver,
}
+static int
+qemuPrepareVarstore(virQEMUDriver *driver,
+ virDomainDef *def,
+ bool reset_nvram)
+{
+ virDomainLoaderDef *loader = def->os.loader;
+ virDomainVarstoreDef *varstore = def->os.varstore;
+
+ if (!loader || !varstore)
+ return 0;
+
+ VIR_DEBUG("varstore='%s'", NULLSTR(varstore->path));
+
+ if (qemuPrepareNVRAMFileCommon(driver, varstore->path,
+ varstore->template, reset_nvram) < 0)
+ return -1;
+
+ return 0;
+}
+
+
static void
qemuLogOperation(virDomainObj *vm,
const char *msg,
@@ -7795,6 +7816,7 @@ qemuProcessPrepareHost(virQEMUDriver *driver,
unsigned int hostdev_flags = 0;
qemuDomainObjPrivate *priv = vm->privateData;
g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
+ bool reset_nvram = !!(flags & VIR_QEMU_PROCESS_START_RESET_NVRAM);
/*
* Create all per-domain directories in order to make sure domain
@@ -7804,8 +7826,10 @@ qemuProcessPrepareHost(virQEMUDriver *driver,
qemuProcessMakeDir(driver, vm, priv->channelTargetDir) < 0)
return -1;
- if (qemuPrepareNVRAM(driver, vm->def,
- !!(flags & VIR_QEMU_PROCESS_START_RESET_NVRAM)) < 0)
+ if (qemuPrepareNVRAM(driver, vm->def, reset_nvram) < 0)
+ return -1;
+
+ if (qemuPrepareVarstore(driver, vm->def, reset_nvram) < 0)
return -1;
if (vm->def->vsock) {
--
2.53.0

View File

@ -1,124 +0,0 @@
From 53b691e4d85f8a442f14ecf4b3bf0b17d607fb2b Mon Sep 17 00:00:00 2001
Message-ID: <53b691e4d85f8a442f14ecf4b3bf0b17d607fb2b.1720800605.git.jdenemar@redhat.com>
From: Jiri Denemark <jdenemar@redhat.com>
Date: Thu, 11 Jul 2024 13:49:09 +0200
Subject: [PATCH] qemu: Don't leave beingDestroyed=true on inactive domain
Recent commit v10.4.0-87-gd9935a5c4f made a reasonable change to only
reset beingDestroyed back to false when vm->def->id is reset to make
sure other code can detect a domain is (about to become) inactive. It
even added a comment saying any caller of qemuProcessBeginStopJob is
supposed to call qemuProcessStop to clear beingDestroyed. But not every
caller really does so because they first call qemuProcessBeginStopJob
and then check whether a domain is still running. If not the
qemuProcessStop call is skipped leaving beingDestroyed=true. In case of
a persistent domain this may block incoming migrations of such domain as
the migration code would think the domain died unexpectedly (even though
it's still running).
The qemuProcessBeginStopJob function is a wrapper around
virDomainObjBeginJob, but virDomainObjEndJob was used directly for
cleanup. This patch introduces a new qemuProcessEndStopJob wrapper
around virDomainObjEndJob to properly undo everything
qemuProcessBeginStopJob did.
https://issues.redhat.com/browse/RHEL-43309
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
Reviewed-by: Peter Krempa <pkrempa@redhat.com>
(cherry picked from commit bec903cae84c21850d47a1b4d3ab57ca81189519)
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
---
src/qemu/qemu_driver.c | 4 ++--
src/qemu/qemu_process.c | 20 ++++++++++++++++----
src/qemu/qemu_process.h | 1 +
3 files changed, 19 insertions(+), 6 deletions(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index fc1704f4fc..d9073b2154 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -2115,7 +2115,7 @@ qemuDomainDestroyFlags(virDomainPtr dom,
endjob:
if (ret == 0)
qemuDomainRemoveInactive(driver, vm, 0, false);
- virDomainObjEndJob(vm);
+ qemuProcessEndStopJob(vm);
cleanup:
virDomainObjEndAPI(&vm);
@@ -3901,7 +3901,7 @@ processMonitorEOFEvent(virQEMUDriver *driver,
endjob:
qemuDomainRemoveInactive(driver, vm, 0, false);
- virDomainObjEndJob(vm);
+ qemuProcessEndStopJob(vm);
}
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index b9b6ccf1de..bea42d38c6 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -8422,7 +8422,8 @@ qemuProcessKill(virDomainObj *vm, unsigned int flags)
* qemuProcessBeginStopJob:
*
* Stop all current jobs by killing the domain and start a new one for
- * qemuProcessStop.
+ * qemuProcessStop. The caller has to make sure qemuProcessEndStopJob is
+ * called to properly cleanup the job.
*/
int
qemuProcessBeginStopJob(virDomainObj *vm,
@@ -8449,8 +8450,9 @@ qemuProcessBeginStopJob(virDomainObj *vm,
goto error;
/* priv->beingDestroyed is deliberately left set to 'true' here. Caller
- * is supposed to call qemuProcessStop, which will reset it after
- * 'vm->def->id' is set to -1 */
+ * is supposed to call qemuProcessStop (which will reset it after
+ * 'vm->def->id' is set to -1) and/or qemuProcessEndStopJob to do proper
+ * cleanup. */
return 0;
error:
@@ -8459,6 +8461,16 @@ qemuProcessBeginStopJob(virDomainObj *vm,
}
+void
+qemuProcessEndStopJob(virDomainObj *vm)
+{
+ if (!virDomainObjIsActive(vm))
+ QEMU_DOMAIN_PRIVATE(vm)->beingDestroyed = false;
+
+ virDomainObjEndJob(vm);
+}
+
+
void qemuProcessStop(virQEMUDriver *driver,
virDomainObj *vm,
virDomainShutoffReason reason,
@@ -8801,7 +8813,7 @@ qemuProcessAutoDestroy(virDomainObj *dom,
qemuDomainRemoveInactive(driver, dom, 0, false);
- virDomainObjEndJob(dom);
+ qemuProcessEndStopJob(dom);
virObjectEventStateQueue(driver->domainEventState, event);
}
diff --git a/src/qemu/qemu_process.h b/src/qemu/qemu_process.h
index c1ea949215..cb67bfcd2d 100644
--- a/src/qemu/qemu_process.h
+++ b/src/qemu/qemu_process.h
@@ -169,6 +169,7 @@ typedef enum {
int qemuProcessBeginStopJob(virDomainObj *vm,
virDomainJob job,
bool forceKill);
+void qemuProcessEndStopJob(virDomainObj *vm);
void qemuProcessStop(virQEMUDriver *driver,
virDomainObj *vm,
virDomainShutoffReason reason,
--
2.45.2

View File

@ -0,0 +1,144 @@
From 92a7fef67b736e20c8e94f3407df7a984ee59102 Mon Sep 17 00:00:00 2001
Message-ID: <92a7fef67b736e20c8e94f3407df7a984ee59102.1771336681.git.jdenemar@redhat.com>
From: Peter Krempa <pkrempa@redhat.com>
Date: Thu, 29 Jan 2026 11:15:04 +0100
Subject: [PATCH] qemu: Extract disk setup done via QMP into a separate helper
Introduce 'qemuProcessSetupDiskPropsRuntime' helper function which will
collect all code used for runtime setup of a disk.
This is currently old-style throttling.
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit 1789a0f8a3623e8f0f6e50730feb58e3d8c48376)
https://issues.redhat.com/browse/RHEL-147866 [rhel-9.8]
https://issues.redhat.com/browse/RHEL-131335 [rhel-10.2]
Conflicts:
- Commit b9b9092c9c1f8b42e311c524d9fc4a8e73ae28a6 which dropped disk
property refresh was not backported, thus the context around the call
to qemuProcessSetupDiskPropsRuntime was different
---
src/qemu/qemu_hotplug.c | 23 +++++------------------
src/qemu/qemu_process.c | 37 +++++++++++++++++++++++++++----------
src/qemu/qemu_process.h | 3 +++
3 files changed, 35 insertions(+), 28 deletions(-)
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index fb426deb1a..f2dc4469a3 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -569,13 +569,8 @@ qemuDomainChangeMediaBlockdev(virDomainObj *vm,
}
/* set throttling for the new image */
- if (rc == 0 &&
- !virStorageSourceIsEmpty(newsrc) &&
- qemuDiskConfigBlkdeviotuneEnabled(disk)) {
- rc = qemuMonitorSetBlockIoThrottle(priv->mon,
- diskPriv->qomName,
- &disk->blkdeviotune);
- }
+ if (rc == 0)
+ rc = qemuProcessSetupDiskPropsRuntime(priv->mon, disk);
if (rc == 0)
rc = qemuMonitorBlockdevTrayClose(priv->mon, diskPriv->qomName);
@@ -795,21 +790,13 @@ qemuDomainAttachDiskGeneric(virDomainObj *vm,
if (rc == 0)
rc = qemuMonitorAddDeviceProps(priv->mon, &devprops);
- /* Setup throttling of disk via block_set_io_throttle QMP command. This
- * is a hack until the 'throttle' blockdev driver will support modification
- * of the trhottle group. See also qemuProcessSetupDiskThrottlingBlockdev.
- * As there isn't anything sane to do if this fails, let's just return
- * success.
- */
if (rc == 0) {
qemuDomainDiskPrivate *diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk);
g_autoptr(GHashTable) blockinfo = NULL;
- if (qemuDiskConfigBlkdeviotuneEnabled(disk)) {
- if (qemuMonitorSetBlockIoThrottle(priv->mon, diskPriv->qomName,
- &disk->blkdeviotune) < 0)
- VIR_WARN("failed to set blkdeviotune for '%s' of '%s'", disk->dst, vm->def->name);
- }
+ /* There isn't anything sane to do if this fails (rollback would
+ * require hot-unplug), let's just return success. */
+ ignore_value(qemuProcessSetupDiskPropsRuntime(priv->mon, disk));
if ((blockinfo = qemuMonitorGetBlockInfo(priv->mon))) {
struct qemuDomainDiskInfo *diskinfo;
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index d8f0c78fd1..c99bb36c93 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -7937,6 +7937,32 @@ qemuProcessGenID(virDomainObj *vm,
}
+/**
+ * qemuProcessSetupDiskPropsRuntime:
+ * @mon: qemu monitor object
+ * @disk: disk definition
+ *
+ * This function expects that caller already entered 'monitor' context.
+ *
+ * Sets up disk properties which are only possible to be set in runtime.
+ */
+int
+qemuProcessSetupDiskPropsRuntime(qemuMonitor *mon,
+ virDomainDiskDef *disk)
+{
+ if (virStorageSourceIsEmpty(disk->src))
+ return 0;
+
+ if (qemuDiskConfigBlkdeviotuneEnabled(disk) &&
+ qemuMonitorSetBlockIoThrottle(mon,
+ QEMU_DOMAIN_DISK_PRIVATE(disk)->qomName,
+ &disk->blkdeviotune) < 0)
+ return -1;
+
+ return 0;
+}
+
+
/**
* qemuProcessSetupDiskThrottling:
*
@@ -7960,16 +7986,7 @@ qemuProcessSetupDiskThrottling(virDomainObj *vm,
for (i = 0; i < vm->def->ndisks; i++) {
virDomainDiskDef *disk = vm->def->disks[i];
- /* Setting throttling for empty drives fails */
- if (virStorageSourceIsEmpty(disk->src))
- continue;
-
- if (!qemuDiskConfigBlkdeviotuneEnabled(disk))
- continue;
-
- if (qemuMonitorSetBlockIoThrottle(qemuDomainGetMonitor(vm),
- QEMU_DOMAIN_DISK_PRIVATE(disk)->qomName,
- &disk->blkdeviotune) < 0)
+ if (qemuProcessSetupDiskPropsRuntime(qemuDomainGetMonitor(vm), disk) < 0)
goto cleanup;
}
diff --git a/src/qemu/qemu_process.h b/src/qemu/qemu_process.h
index 426e11d79e..df78b00abb 100644
--- a/src/qemu/qemu_process.h
+++ b/src/qemu/qemu_process.h
@@ -146,6 +146,9 @@ int qemuProcessPrepareHostStorageSourceChain(virDomainObj *vm,
int qemuProcessPrepareHostStorageDisk(virDomainObj *vm,
virDomainDiskDef *disk);
+int qemuProcessSetupDiskPropsRuntime(qemuMonitor *mon,
+ virDomainDiskDef *disk);
+
int qemuProcessDeleteThreadContext(virDomainObj *vm);
int qemuProcessLaunch(virConnectPtr conn,
--
2.53.0

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,713 @@
From 636b8f50486f3007be1b92ddb84f326f58d168d8 Mon Sep 17 00:00:00 2001
Message-ID: <636b8f50486f3007be1b92ddb84f326f58d168d8.1770825107.git.jdenemar@redhat.com>
From: Jean-Louis Dupond <jean-louis@dupond.be>
Date: Thu, 5 Feb 2026 14:18:42 +0100
Subject: [PATCH] qemu: Ignore cmp_legacy CPU flag
Since commit 99a637a8 in qemu 10.0, the way the cmp_legacy flag is
reported changed. The same way as happend with the 'ht' flag in commit
c6bd2dd634208, which was fixed in libvirt since commit ba16113c.
This causes migrations from a hypervisor running a qemu version before
that commit to a hypervisor running qemu after that commit fails
with the following error:
guest CPU doesn't match specification: extra features: cmp_legacy
We can just ignore this flag, just like we did with the 'ht' flag.
Signed-off-by: Jean-Louis Dupond <jean-louis@dupond.be>
Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
(cherry picked from commit fc5840b4980045a05b8973900cdbe36162e48331)
https://issues.redhat.com/browse/RHEL-148494
Conflicts:
tests/qemuxmlconfdata/cpu-host-model-fallback-kvm.x86_64-latest.args
tests/qemuxmlconfdata/cpu-host-model-features.x86_64-latest.args
tests/qemuxmlconfdata/cpu-host-model-kvm.x86_64-latest.args
tests/qemuxmlconfdata/cpu-host-model-nofallback-kvm.x86_64-latest.args
- upstream commit v11.10.0-78-g380764992d
(qemucapabilitiesdata: Re-generate 'caps_10.2.0_x86_64')
that added rdseed=off to test files is not backported
tests/qemuxmlconfdata/memory-hotplug-numa-preferred.x86_64-latest.args
- missing downstream, it was added upstream after the last
rebase
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
---
src/qemu/qemu_capabilities.c | 1 +
.../cpu-host-model-fallback-kvm.x86_64-10.0.0.args | 2 +-
.../cpu-host-model-fallback-kvm.x86_64-10.1.0.args | 2 +-
.../cpu-host-model-fallback-kvm.x86_64-6.2.0.args | 2 +-
.../cpu-host-model-fallback-kvm.x86_64-7.0.0.args | 2 +-
.../cpu-host-model-fallback-kvm.x86_64-7.1.0.args | 2 +-
.../cpu-host-model-fallback-kvm.x86_64-7.2.0.args | 2 +-
.../cpu-host-model-fallback-kvm.x86_64-8.0.0.args | 2 +-
.../cpu-host-model-fallback-kvm.x86_64-8.1.0.args | 2 +-
.../cpu-host-model-fallback-kvm.x86_64-8.2.0.args | 2 +-
.../cpu-host-model-fallback-kvm.x86_64-9.0.0.args | 2 +-
.../cpu-host-model-fallback-kvm.x86_64-9.1.0.args | 2 +-
.../cpu-host-model-fallback-kvm.x86_64-9.2.0.args | 2 +-
.../cpu-host-model-fallback-kvm.x86_64-latest.args | 2 +-
.../cpu-host-model-fallback-tcg.x86_64-10.1.0.args | 2 +-
.../cpu-host-model-fallback-tcg.x86_64-latest.args | 2 +-
.../qemuxmlconfdata/cpu-host-model-features.x86_64-latest.args | 2 +-
tests/qemuxmlconfdata/cpu-host-model-kvm.x86_64-10.0.0.args | 2 +-
tests/qemuxmlconfdata/cpu-host-model-kvm.x86_64-10.1.0.args | 2 +-
tests/qemuxmlconfdata/cpu-host-model-kvm.x86_64-6.2.0.args | 2 +-
tests/qemuxmlconfdata/cpu-host-model-kvm.x86_64-7.0.0.args | 2 +-
tests/qemuxmlconfdata/cpu-host-model-kvm.x86_64-7.1.0.args | 2 +-
tests/qemuxmlconfdata/cpu-host-model-kvm.x86_64-7.2.0.args | 2 +-
tests/qemuxmlconfdata/cpu-host-model-kvm.x86_64-8.0.0.args | 2 +-
tests/qemuxmlconfdata/cpu-host-model-kvm.x86_64-8.1.0.args | 2 +-
tests/qemuxmlconfdata/cpu-host-model-kvm.x86_64-8.2.0.args | 2 +-
tests/qemuxmlconfdata/cpu-host-model-kvm.x86_64-9.0.0.args | 2 +-
tests/qemuxmlconfdata/cpu-host-model-kvm.x86_64-9.1.0.args | 2 +-
tests/qemuxmlconfdata/cpu-host-model-kvm.x86_64-9.2.0.args | 2 +-
tests/qemuxmlconfdata/cpu-host-model-kvm.x86_64-latest.args | 2 +-
.../cpu-host-model-nofallback-kvm.x86_64-10.0.0.args | 2 +-
.../cpu-host-model-nofallback-kvm.x86_64-10.1.0.args | 2 +-
.../cpu-host-model-nofallback-kvm.x86_64-6.2.0.args | 2 +-
.../cpu-host-model-nofallback-kvm.x86_64-7.0.0.args | 2 +-
.../cpu-host-model-nofallback-kvm.x86_64-7.1.0.args | 2 +-
.../cpu-host-model-nofallback-kvm.x86_64-7.2.0.args | 2 +-
.../cpu-host-model-nofallback-kvm.x86_64-8.0.0.args | 2 +-
.../cpu-host-model-nofallback-kvm.x86_64-8.1.0.args | 2 +-
.../cpu-host-model-nofallback-kvm.x86_64-8.2.0.args | 2 +-
.../cpu-host-model-nofallback-kvm.x86_64-9.0.0.args | 2 +-
.../cpu-host-model-nofallback-kvm.x86_64-9.1.0.args | 2 +-
.../cpu-host-model-nofallback-kvm.x86_64-9.2.0.args | 2 +-
.../cpu-host-model-nofallback-kvm.x86_64-latest.args | 2 +-
.../cpu-host-model-nofallback-tcg.x86_64-10.1.0.args | 2 +-
.../cpu-host-model-nofallback-tcg.x86_64-latest.args | 2 +-
tests/qemuxmlconfdata/cpu-host-model-tcg.x86_64-10.1.0.args | 2 +-
tests/qemuxmlconfdata/cpu-host-model-tcg.x86_64-latest.args | 2 +-
tests/qemuxmlconfdata/cpu-translation.x86_64-latest.args | 2 +-
48 files changed, 48 insertions(+), 47 deletions(-)
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index 92b863a826..d738805ee8 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -3772,6 +3772,7 @@ const char *ignoredFeatures[] = {
"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 */
+ "cmp_legacy", /* ignored by QEMU, set according to topology */
};
bool
diff --git a/tests/qemuxmlconfdata/cpu-host-model-fallback-kvm.x86_64-10.0.0.args b/tests/qemuxmlconfdata/cpu-host-model-fallback-kvm.x86_64-10.0.0.args
index edd334dd8b..08f37274b2 100644
--- a/tests/qemuxmlconfdata/cpu-host-model-fallback-kvm.x86_64-10.0.0.args
+++ b/tests/qemuxmlconfdata/cpu-host-model-fallback-kvm.x86_64-10.0.0.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-i440fx-10.0,usb=off,dump-guest-core=off,memory-backend=pc.ram,acpi=off \
-accel kvm \
--cpu EPYC-Rome,x2apic=on,tsc-deadline=on,hypervisor=on,tsc-adjust=on,stibp=on,arch-capabilities=on,ssbd=on,cmp-legacy=on,overflow-recov=on,succor=on,amd-ssbd=on,virt-ssbd=on,lbrv=on,tsc-scale=on,vmcb-clean=on,flushbyasid=on,pause-filter=on,pfthreshold=on,v-vmsave-vmload=on,vgif=on,svme-addr-chk=on,lfence-always-serializing=on,null-sel-clr-base=on,ibpb-brtype=on,rdctl-no=on,skip-l1dfl-vmentry=on,mds-no=on,pschange-mc-no=on,gds-no=on,rfds-no=on,xsaves=off \
+-cpu EPYC-Rome,x2apic=on,tsc-deadline=on,hypervisor=on,tsc-adjust=on,stibp=on,arch-capabilities=on,ssbd=on,overflow-recov=on,succor=on,amd-ssbd=on,virt-ssbd=on,lbrv=on,tsc-scale=on,vmcb-clean=on,flushbyasid=on,pause-filter=on,pfthreshold=on,v-vmsave-vmload=on,vgif=on,svme-addr-chk=on,lfence-always-serializing=on,null-sel-clr-base=on,ibpb-brtype=on,rdctl-no=on,skip-l1dfl-vmentry=on,mds-no=on,pschange-mc-no=on,gds-no=on,rfds-no=on,xsaves=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-host-model-fallback-kvm.x86_64-10.1.0.args b/tests/qemuxmlconfdata/cpu-host-model-fallback-kvm.x86_64-10.1.0.args
index 57982574eb..e4044a0c64 100644
--- a/tests/qemuxmlconfdata/cpu-host-model-fallback-kvm.x86_64-10.1.0.args
+++ b/tests/qemuxmlconfdata/cpu-host-model-fallback-kvm.x86_64-10.1.0.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-i440fx-10.1,usb=off,dump-guest-core=off,memory-backend=pc.ram,acpi=off \
-accel kvm \
--cpu EPYC-Rome,x2apic=on,tsc-deadline=on,hypervisor=on,tsc-adjust=on,stibp=on,ssbd=on,cmp-legacy=on,overflow-recov=on,succor=on,amd-ssbd=on,virt-ssbd=on,lbrv=on,tsc-scale=on,vmcb-clean=on,flushbyasid=on,pause-filter=on,pfthreshold=on,v-vmsave-vmload=on,vgif=on,svme-addr-chk=on,lfence-always-serializing=on,null-sel-clr-base=on,ibpb-brtype=on,xsaves=off \
+-cpu EPYC-Rome,x2apic=on,tsc-deadline=on,hypervisor=on,tsc-adjust=on,stibp=on,ssbd=on,overflow-recov=on,succor=on,amd-ssbd=on,virt-ssbd=on,lbrv=on,tsc-scale=on,vmcb-clean=on,flushbyasid=on,pause-filter=on,pfthreshold=on,v-vmsave-vmload=on,vgif=on,svme-addr-chk=on,lfence-always-serializing=on,null-sel-clr-base=on,ibpb-brtype=on,xsaves=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-host-model-fallback-kvm.x86_64-6.2.0.args b/tests/qemuxmlconfdata/cpu-host-model-fallback-kvm.x86_64-6.2.0.args
index 4aa9011fe8..e8a9aceb4a 100644
--- a/tests/qemuxmlconfdata/cpu-host-model-fallback-kvm.x86_64-6.2.0.args
+++ b/tests/qemuxmlconfdata/cpu-host-model-fallback-kvm.x86_64-6.2.0.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-i440fx-6.2,usb=off,dump-guest-core=off,memory-backend=pc.ram \
-accel kvm \
--cpu EPYC-Rome,x2apic=on,tsc-deadline=on,hypervisor=on,tsc-adjust=on,stibp=on,arch-capabilities=on,ssbd=on,xsaves=on,cmp-legacy=on,amd-ssbd=on,virt-ssbd=on,svme-addr-chk=on,rdctl-no=on,skip-l1dfl-vmentry=on,mds-no=on,pschange-mc-no=on \
+-cpu EPYC-Rome,x2apic=on,tsc-deadline=on,hypervisor=on,tsc-adjust=on,stibp=on,arch-capabilities=on,ssbd=on,xsaves=on,amd-ssbd=on,virt-ssbd=on,svme-addr-chk=on,rdctl-no=on,skip-l1dfl-vmentry=on,mds-no=on,pschange-mc-no=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-fallback-kvm.x86_64-7.0.0.args b/tests/qemuxmlconfdata/cpu-host-model-fallback-kvm.x86_64-7.0.0.args
index e944e69cfd..0df6ce9e3d 100644
--- a/tests/qemuxmlconfdata/cpu-host-model-fallback-kvm.x86_64-7.0.0.args
+++ b/tests/qemuxmlconfdata/cpu-host-model-fallback-kvm.x86_64-7.0.0.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-i440fx-7.0,usb=off,dump-guest-core=off,memory-backend=pc.ram \
-accel kvm \
--cpu EPYC-Rome,x2apic=on,tsc-deadline=on,hypervisor=on,tsc-adjust=on,stibp=on,arch-capabilities=on,ssbd=on,xsaves=on,cmp-legacy=on,amd-ssbd=on,virt-ssbd=on,tsc-scale=on,svme-addr-chk=on,rdctl-no=on,skip-l1dfl-vmentry=on,mds-no=on,pschange-mc-no=on \
+-cpu EPYC-Rome,x2apic=on,tsc-deadline=on,hypervisor=on,tsc-adjust=on,stibp=on,arch-capabilities=on,ssbd=on,xsaves=on,amd-ssbd=on,virt-ssbd=on,tsc-scale=on,svme-addr-chk=on,rdctl-no=on,skip-l1dfl-vmentry=on,mds-no=on,pschange-mc-no=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-fallback-kvm.x86_64-7.1.0.args b/tests/qemuxmlconfdata/cpu-host-model-fallback-kvm.x86_64-7.1.0.args
index d9edda2733..b4a91fa921 100644
--- a/tests/qemuxmlconfdata/cpu-host-model-fallback-kvm.x86_64-7.1.0.args
+++ b/tests/qemuxmlconfdata/cpu-host-model-fallback-kvm.x86_64-7.1.0.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-i440fx-7.1,usb=off,dump-guest-core=off,memory-backend=pc.ram \
-accel kvm \
--cpu EPYC-Rome,x2apic=on,tsc-deadline=on,hypervisor=on,tsc-adjust=on,stibp=on,arch-capabilities=on,ssbd=on,xsaves=on,cmp-legacy=on,amd-ssbd=on,virt-ssbd=on,tsc-scale=on,vmcb-clean=on,svme-addr-chk=on,rdctl-no=on,skip-l1dfl-vmentry=on,mds-no=on,pschange-mc-no=on \
+-cpu EPYC-Rome,x2apic=on,tsc-deadline=on,hypervisor=on,tsc-adjust=on,stibp=on,arch-capabilities=on,ssbd=on,xsaves=on,amd-ssbd=on,virt-ssbd=on,tsc-scale=on,vmcb-clean=on,svme-addr-chk=on,rdctl-no=on,skip-l1dfl-vmentry=on,mds-no=on,pschange-mc-no=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-fallback-kvm.x86_64-7.2.0.args b/tests/qemuxmlconfdata/cpu-host-model-fallback-kvm.x86_64-7.2.0.args
index 1d1839b7fa..5d69199876 100644
--- a/tests/qemuxmlconfdata/cpu-host-model-fallback-kvm.x86_64-7.2.0.args
+++ b/tests/qemuxmlconfdata/cpu-host-model-fallback-kvm.x86_64-7.2.0.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-i440fx-7.2,usb=off,dump-guest-core=off,memory-backend=pc.ram \
-accel kvm \
--cpu EPYC-Rome,x2apic=on,tsc-deadline=on,hypervisor=on,tsc-adjust=on,stibp=on,arch-capabilities=on,ssbd=on,xsaves=on,cmp-legacy=on,amd-ssbd=on,virt-ssbd=on,lbrv=on,tsc-scale=on,vmcb-clean=on,pause-filter=on,pfthreshold=on,v-vmsave-vmload=on,vgif=on,svme-addr-chk=on,rdctl-no=on,skip-l1dfl-vmentry=on,mds-no=on,pschange-mc-no=on \
+-cpu EPYC-Rome,x2apic=on,tsc-deadline=on,hypervisor=on,tsc-adjust=on,stibp=on,arch-capabilities=on,ssbd=on,xsaves=on,amd-ssbd=on,virt-ssbd=on,lbrv=on,tsc-scale=on,vmcb-clean=on,pause-filter=on,pfthreshold=on,v-vmsave-vmload=on,vgif=on,svme-addr-chk=on,rdctl-no=on,skip-l1dfl-vmentry=on,mds-no=on,pschange-mc-no=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-fallback-kvm.x86_64-8.0.0.args b/tests/qemuxmlconfdata/cpu-host-model-fallback-kvm.x86_64-8.0.0.args
index 8278629ee7..e7b424819e 100644
--- a/tests/qemuxmlconfdata/cpu-host-model-fallback-kvm.x86_64-8.0.0.args
+++ b/tests/qemuxmlconfdata/cpu-host-model-fallback-kvm.x86_64-8.0.0.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-i440fx-8.0,usb=off,dump-guest-core=off,memory-backend=pc.ram,acpi=off \
-accel kvm \
--cpu EPYC-Rome,x2apic=on,tsc-deadline=on,hypervisor=on,tsc-adjust=on,stibp=on,arch-capabilities=on,ssbd=on,xsaves=on,cmp-legacy=on,amd-ssbd=on,virt-ssbd=on,lbrv=on,tsc-scale=on,vmcb-clean=on,pause-filter=on,pfthreshold=on,v-vmsave-vmload=on,vgif=on,svme-addr-chk=on,rdctl-no=on,skip-l1dfl-vmentry=on,mds-no=on,pschange-mc-no=on \
+-cpu EPYC-Rome,x2apic=on,tsc-deadline=on,hypervisor=on,tsc-adjust=on,stibp=on,arch-capabilities=on,ssbd=on,xsaves=on,amd-ssbd=on,virt-ssbd=on,lbrv=on,tsc-scale=on,vmcb-clean=on,pause-filter=on,pfthreshold=on,v-vmsave-vmload=on,vgif=on,svme-addr-chk=on,rdctl-no=on,skip-l1dfl-vmentry=on,mds-no=on,pschange-mc-no=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-fallback-kvm.x86_64-8.1.0.args b/tests/qemuxmlconfdata/cpu-host-model-fallback-kvm.x86_64-8.1.0.args
index 3b733a3c5d..58ad565dba 100644
--- a/tests/qemuxmlconfdata/cpu-host-model-fallback-kvm.x86_64-8.1.0.args
+++ b/tests/qemuxmlconfdata/cpu-host-model-fallback-kvm.x86_64-8.1.0.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-i440fx-8.1,usb=off,dump-guest-core=off,memory-backend=pc.ram,acpi=off \
-accel kvm \
--cpu EPYC-Rome,x2apic=on,tsc-deadline=on,hypervisor=on,tsc-adjust=on,stibp=on,arch-capabilities=on,ssbd=on,cmp-legacy=on,amd-ssbd=on,virt-ssbd=on,lbrv=on,tsc-scale=on,vmcb-clean=on,pause-filter=on,pfthreshold=on,v-vmsave-vmload=on,vgif=on,svme-addr-chk=on,lfence-always-serializing=on,null-sel-clr-base=on,rdctl-no=on,skip-l1dfl-vmentry=on,mds-no=on,pschange-mc-no=on,xsaves=off \
+-cpu EPYC-Rome,x2apic=on,tsc-deadline=on,hypervisor=on,tsc-adjust=on,stibp=on,arch-capabilities=on,ssbd=on,amd-ssbd=on,virt-ssbd=on,lbrv=on,tsc-scale=on,vmcb-clean=on,pause-filter=on,pfthreshold=on,v-vmsave-vmload=on,vgif=on,svme-addr-chk=on,lfence-always-serializing=on,null-sel-clr-base=on,rdctl-no=on,skip-l1dfl-vmentry=on,mds-no=on,pschange-mc-no=on,xsaves=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-host-model-fallback-kvm.x86_64-8.2.0.args b/tests/qemuxmlconfdata/cpu-host-model-fallback-kvm.x86_64-8.2.0.args
index 73296c7df0..fa1b674fa5 100644
--- a/tests/qemuxmlconfdata/cpu-host-model-fallback-kvm.x86_64-8.2.0.args
+++ b/tests/qemuxmlconfdata/cpu-host-model-fallback-kvm.x86_64-8.2.0.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-i440fx-8.2,usb=off,dump-guest-core=off,memory-backend=pc.ram,acpi=off \
-accel kvm \
--cpu EPYC-Rome,x2apic=on,tsc-deadline=on,hypervisor=on,tsc-adjust=on,stibp=on,arch-capabilities=on,ssbd=on,cmp-legacy=on,amd-ssbd=on,virt-ssbd=on,lbrv=on,tsc-scale=on,vmcb-clean=on,pause-filter=on,pfthreshold=on,v-vmsave-vmload=on,vgif=on,svme-addr-chk=on,lfence-always-serializing=on,null-sel-clr-base=on,rdctl-no=on,skip-l1dfl-vmentry=on,mds-no=on,pschange-mc-no=on,gds-no=on,xsaves=off \
+-cpu EPYC-Rome,x2apic=on,tsc-deadline=on,hypervisor=on,tsc-adjust=on,stibp=on,arch-capabilities=on,ssbd=on,amd-ssbd=on,virt-ssbd=on,lbrv=on,tsc-scale=on,vmcb-clean=on,pause-filter=on,pfthreshold=on,v-vmsave-vmload=on,vgif=on,svme-addr-chk=on,lfence-always-serializing=on,null-sel-clr-base=on,rdctl-no=on,skip-l1dfl-vmentry=on,mds-no=on,pschange-mc-no=on,gds-no=on,xsaves=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-host-model-fallback-kvm.x86_64-9.0.0.args b/tests/qemuxmlconfdata/cpu-host-model-fallback-kvm.x86_64-9.0.0.args
index 8f8b74fa56..fc9985f901 100644
--- a/tests/qemuxmlconfdata/cpu-host-model-fallback-kvm.x86_64-9.0.0.args
+++ b/tests/qemuxmlconfdata/cpu-host-model-fallback-kvm.x86_64-9.0.0.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-i440fx-9.0,usb=off,dump-guest-core=off,memory-backend=pc.ram,acpi=off \
-accel kvm \
--cpu EPYC-Rome,x2apic=on,tsc-deadline=on,hypervisor=on,tsc-adjust=on,stibp=on,arch-capabilities=on,ssbd=on,cmp-legacy=on,amd-ssbd=on,virt-ssbd=on,lbrv=on,tsc-scale=on,vmcb-clean=on,pause-filter=on,pfthreshold=on,v-vmsave-vmload=on,vgif=on,svme-addr-chk=on,lfence-always-serializing=on,null-sel-clr-base=on,rdctl-no=on,skip-l1dfl-vmentry=on,mds-no=on,pschange-mc-no=on,gds-no=on,xsaves=off \
+-cpu EPYC-Rome,x2apic=on,tsc-deadline=on,hypervisor=on,tsc-adjust=on,stibp=on,arch-capabilities=on,ssbd=on,amd-ssbd=on,virt-ssbd=on,lbrv=on,tsc-scale=on,vmcb-clean=on,pause-filter=on,pfthreshold=on,v-vmsave-vmload=on,vgif=on,svme-addr-chk=on,lfence-always-serializing=on,null-sel-clr-base=on,rdctl-no=on,skip-l1dfl-vmentry=on,mds-no=on,pschange-mc-no=on,gds-no=on,xsaves=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-host-model-fallback-kvm.x86_64-9.1.0.args b/tests/qemuxmlconfdata/cpu-host-model-fallback-kvm.x86_64-9.1.0.args
index c2f394bf09..1db86cb31e 100644
--- a/tests/qemuxmlconfdata/cpu-host-model-fallback-kvm.x86_64-9.1.0.args
+++ b/tests/qemuxmlconfdata/cpu-host-model-fallback-kvm.x86_64-9.1.0.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-i440fx-9.1,usb=off,dump-guest-core=off,memory-backend=pc.ram,acpi=off \
-accel kvm \
--cpu EPYC-Rome,x2apic=on,tsc-deadline=on,hypervisor=on,tsc-adjust=on,stibp=on,arch-capabilities=on,ssbd=on,cmp-legacy=on,overflow-recov=on,succor=on,amd-ssbd=on,virt-ssbd=on,lbrv=on,tsc-scale=on,vmcb-clean=on,flushbyasid=on,pause-filter=on,pfthreshold=on,v-vmsave-vmload=on,vgif=on,svme-addr-chk=on,lfence-always-serializing=on,null-sel-clr-base=on,rdctl-no=on,skip-l1dfl-vmentry=on,mds-no=on,pschange-mc-no=on,gds-no=on,rfds-no=on,xsaves=off \
+-cpu EPYC-Rome,x2apic=on,tsc-deadline=on,hypervisor=on,tsc-adjust=on,stibp=on,arch-capabilities=on,ssbd=on,overflow-recov=on,succor=on,amd-ssbd=on,virt-ssbd=on,lbrv=on,tsc-scale=on,vmcb-clean=on,flushbyasid=on,pause-filter=on,pfthreshold=on,v-vmsave-vmload=on,vgif=on,svme-addr-chk=on,lfence-always-serializing=on,null-sel-clr-base=on,rdctl-no=on,skip-l1dfl-vmentry=on,mds-no=on,pschange-mc-no=on,gds-no=on,rfds-no=on,xsaves=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-host-model-fallback-kvm.x86_64-9.2.0.args b/tests/qemuxmlconfdata/cpu-host-model-fallback-kvm.x86_64-9.2.0.args
index 35c8d397c4..4dcd9332cb 100644
--- a/tests/qemuxmlconfdata/cpu-host-model-fallback-kvm.x86_64-9.2.0.args
+++ b/tests/qemuxmlconfdata/cpu-host-model-fallback-kvm.x86_64-9.2.0.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-i440fx-9.2,usb=off,dump-guest-core=off,memory-backend=pc.ram,acpi=off \
-accel kvm \
--cpu EPYC-Rome,x2apic=on,tsc-deadline=on,hypervisor=on,tsc-adjust=on,stibp=on,arch-capabilities=on,ssbd=on,cmp-legacy=on,overflow-recov=on,succor=on,amd-ssbd=on,virt-ssbd=on,lbrv=on,tsc-scale=on,vmcb-clean=on,flushbyasid=on,pause-filter=on,pfthreshold=on,v-vmsave-vmload=on,vgif=on,svme-addr-chk=on,lfence-always-serializing=on,null-sel-clr-base=on,ibpb-brtype=on,rdctl-no=on,skip-l1dfl-vmentry=on,mds-no=on,pschange-mc-no=on,gds-no=on,rfds-no=on,xsaves=off \
+-cpu EPYC-Rome,x2apic=on,tsc-deadline=on,hypervisor=on,tsc-adjust=on,stibp=on,arch-capabilities=on,ssbd=on,overflow-recov=on,succor=on,amd-ssbd=on,virt-ssbd=on,lbrv=on,tsc-scale=on,vmcb-clean=on,flushbyasid=on,pause-filter=on,pfthreshold=on,v-vmsave-vmload=on,vgif=on,svme-addr-chk=on,lfence-always-serializing=on,null-sel-clr-base=on,ibpb-brtype=on,rdctl-no=on,skip-l1dfl-vmentry=on,mds-no=on,pschange-mc-no=on,gds-no=on,rfds-no=on,xsaves=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-host-model-fallback-kvm.x86_64-latest.args b/tests/qemuxmlconfdata/cpu-host-model-fallback-kvm.x86_64-latest.args
index 6afa8a4c2d..e5b0acb87b 100644
--- a/tests/qemuxmlconfdata/cpu-host-model-fallback-kvm.x86_64-latest.args
+++ b/tests/qemuxmlconfdata/cpu-host-model-fallback-kvm.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 EPYC-Turin,x2apic=on,tsc-deadline=on,hypervisor=on,tsc-adjust=on,spec-ctrl=on,stibp=on,flush-l1d=on,ssbd=on,cmp-legacy=on,virt-ssbd=on,tsa-sq-no=on,tsa-l1-no=on,pcid=off,la57=off \
+-cpu EPYC-Turin,x2apic=on,tsc-deadline=on,hypervisor=on,tsc-adjust=on,spec-ctrl=on,stibp=on,flush-l1d=on,ssbd=on,virt-ssbd=on,tsa-sq-no=on,tsa-l1-no=on,pcid=off,la57=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-host-model-fallback-tcg.x86_64-10.1.0.args b/tests/qemuxmlconfdata/cpu-host-model-fallback-tcg.x86_64-10.1.0.args
index 3b93ed510d..0b67c7f158 100644
--- a/tests/qemuxmlconfdata/cpu-host-model-fallback-tcg.x86_64-10.1.0.args
+++ b/tests/qemuxmlconfdata/cpu-host-model-fallback-tcg.x86_64-10.1.0.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-i440fx-10.1,usb=off,dump-guest-core=off,memory-backend=pc.ram,acpi=off \
-accel tcg \
--cpu EPYC,monitor=on,x2apic=on,hypervisor=on,acpi=on,ss=on,erms=on,mpx=on,clwb=on,umip=on,pku=on,vaes=on,la57=on,rdpid=on,pks=on,fsrm=on,cmpccxadd=on,fzrm=on,fsrs=on,fsrc=on,cmp-legacy=on,3dnowext=on,3dnow=on,xsaveerptr=on,wbnoinvd=on,npt=on,vgif=on,svme-addr-chk=on,no-nested-data-bp=on,null-sel-clr-base=on,vme=off,xsavec=off,misalignsse=off,osvw=off,topoext=off,fxsr-opt=off,nrip-save=off \
+-cpu EPYC,monitor=on,x2apic=on,hypervisor=on,acpi=on,ss=on,erms=on,mpx=on,clwb=on,umip=on,pku=on,vaes=on,la57=on,rdpid=on,pks=on,fsrm=on,cmpccxadd=on,fzrm=on,fsrs=on,fsrc=on,3dnowext=on,3dnow=on,xsaveerptr=on,wbnoinvd=on,npt=on,vgif=on,svme-addr-chk=on,no-nested-data-bp=on,null-sel-clr-base=on,vme=off,xsavec=off,misalignsse=off,osvw=off,topoext=off,fxsr-opt=off,nrip-save=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-host-model-fallback-tcg.x86_64-latest.args b/tests/qemuxmlconfdata/cpu-host-model-fallback-tcg.x86_64-latest.args
index 01cf90bb67..443de62f69 100644
--- a/tests/qemuxmlconfdata/cpu-host-model-fallback-tcg.x86_64-latest.args
+++ b/tests/qemuxmlconfdata/cpu-host-model-fallback-tcg.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 EPYC,monitor=on,x2apic=on,hypervisor=on,acpi=on,ss=on,erms=on,mpx=on,clwb=on,umip=on,pku=on,vaes=on,la57=on,rdpid=on,pks=on,fsrm=on,cmpccxadd=on,fzrm=on,fsrs=on,fsrc=on,cmp-legacy=on,3dnowext=on,3dnow=on,xsaveerptr=on,wbnoinvd=on,npt=on,vgif=on,svme-addr-chk=on,no-nested-data-bp=on,null-sel-clr-base=on,vme=off,xsavec=off,misalignsse=off,osvw=off,topoext=off,fxsr-opt=off,nrip-save=off \
+-cpu EPYC,monitor=on,x2apic=on,hypervisor=on,acpi=on,ss=on,erms=on,mpx=on,clwb=on,umip=on,pku=on,vaes=on,la57=on,rdpid=on,pks=on,fsrm=on,cmpccxadd=on,fzrm=on,fsrs=on,fsrc=on,3dnowext=on,3dnow=on,xsaveerptr=on,wbnoinvd=on,npt=on,vgif=on,svme-addr-chk=on,no-nested-data-bp=on,null-sel-clr-base=on,vme=off,xsavec=off,misalignsse=off,osvw=off,topoext=off,fxsr-opt=off,nrip-save=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-host-model-features.x86_64-latest.args b/tests/qemuxmlconfdata/cpu-host-model-features.x86_64-latest.args
index ce60a39acc..52f636fa77 100644
--- a/tests/qemuxmlconfdata/cpu-host-model-features.x86_64-latest.args
+++ b/tests/qemuxmlconfdata/cpu-host-model-features.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 EPYC-Turin,x2apic=on,tsc-deadline=on,hypervisor=on,tsc-adjust=on,spec-ctrl=on,stibp=on,flush-l1d=on,ssbd=on,cmp-legacy=on,virt-ssbd=on,tsa-sq-no=on,tsa-l1-no=on,pcid=off,la57=off,abm=on,ds=on,invtsc=off \
+-cpu EPYC-Turin,x2apic=on,tsc-deadline=on,hypervisor=on,tsc-adjust=on,spec-ctrl=on,stibp=on,flush-l1d=on,ssbd=on,virt-ssbd=on,tsa-sq-no=on,tsa-l1-no=on,pcid=off,la57=off,abm=on,ds=on,invtsc=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-host-model-kvm.x86_64-10.0.0.args b/tests/qemuxmlconfdata/cpu-host-model-kvm.x86_64-10.0.0.args
index a1c034ec51..7dd5723b98 100644
--- a/tests/qemuxmlconfdata/cpu-host-model-kvm.x86_64-10.0.0.args
+++ b/tests/qemuxmlconfdata/cpu-host-model-kvm.x86_64-10.0.0.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-q35-10.0,usb=off,dump-guest-core=off,memory-backend=pc.ram,acpi=off \
-accel kvm \
--cpu EPYC-Rome,x2apic=on,tsc-deadline=on,hypervisor=on,tsc-adjust=on,stibp=on,arch-capabilities=on,ssbd=on,cmp-legacy=on,overflow-recov=on,succor=on,amd-ssbd=on,virt-ssbd=on,lbrv=on,tsc-scale=on,vmcb-clean=on,flushbyasid=on,pause-filter=on,pfthreshold=on,v-vmsave-vmload=on,vgif=on,svme-addr-chk=on,lfence-always-serializing=on,null-sel-clr-base=on,ibpb-brtype=on,rdctl-no=on,skip-l1dfl-vmentry=on,mds-no=on,pschange-mc-no=on,gds-no=on,rfds-no=on,xsaves=off \
+-cpu EPYC-Rome,x2apic=on,tsc-deadline=on,hypervisor=on,tsc-adjust=on,stibp=on,arch-capabilities=on,ssbd=on,overflow-recov=on,succor=on,amd-ssbd=on,virt-ssbd=on,lbrv=on,tsc-scale=on,vmcb-clean=on,flushbyasid=on,pause-filter=on,pfthreshold=on,v-vmsave-vmload=on,vgif=on,svme-addr-chk=on,lfence-always-serializing=on,null-sel-clr-base=on,ibpb-brtype=on,rdctl-no=on,skip-l1dfl-vmentry=on,mds-no=on,pschange-mc-no=on,gds-no=on,rfds-no=on,xsaves=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-host-model-kvm.x86_64-10.1.0.args b/tests/qemuxmlconfdata/cpu-host-model-kvm.x86_64-10.1.0.args
index ddf940f75c..987baa9b30 100644
--- a/tests/qemuxmlconfdata/cpu-host-model-kvm.x86_64-10.1.0.args
+++ b/tests/qemuxmlconfdata/cpu-host-model-kvm.x86_64-10.1.0.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-q35-10.1,usb=off,dump-guest-core=off,memory-backend=pc.ram,acpi=off \
-accel kvm \
--cpu EPYC-Rome,x2apic=on,tsc-deadline=on,hypervisor=on,tsc-adjust=on,stibp=on,ssbd=on,cmp-legacy=on,overflow-recov=on,succor=on,amd-ssbd=on,virt-ssbd=on,lbrv=on,tsc-scale=on,vmcb-clean=on,flushbyasid=on,pause-filter=on,pfthreshold=on,v-vmsave-vmload=on,vgif=on,svme-addr-chk=on,lfence-always-serializing=on,null-sel-clr-base=on,ibpb-brtype=on,xsaves=off \
+-cpu EPYC-Rome,x2apic=on,tsc-deadline=on,hypervisor=on,tsc-adjust=on,stibp=on,ssbd=on,overflow-recov=on,succor=on,amd-ssbd=on,virt-ssbd=on,lbrv=on,tsc-scale=on,vmcb-clean=on,flushbyasid=on,pause-filter=on,pfthreshold=on,v-vmsave-vmload=on,vgif=on,svme-addr-chk=on,lfence-always-serializing=on,null-sel-clr-base=on,ibpb-brtype=on,xsaves=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-host-model-kvm.x86_64-6.2.0.args b/tests/qemuxmlconfdata/cpu-host-model-kvm.x86_64-6.2.0.args
index f65444948e..4402bad82d 100644
--- a/tests/qemuxmlconfdata/cpu-host-model-kvm.x86_64-6.2.0.args
+++ b/tests/qemuxmlconfdata/cpu-host-model-kvm.x86_64-6.2.0.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-q35-6.2,usb=off,dump-guest-core=off,memory-backend=pc.ram \
-accel kvm \
--cpu EPYC-Rome,x2apic=on,tsc-deadline=on,hypervisor=on,tsc-adjust=on,stibp=on,arch-capabilities=on,ssbd=on,xsaves=on,cmp-legacy=on,amd-ssbd=on,virt-ssbd=on,svme-addr-chk=on,rdctl-no=on,skip-l1dfl-vmentry=on,mds-no=on,pschange-mc-no=on \
+-cpu EPYC-Rome,x2apic=on,tsc-deadline=on,hypervisor=on,tsc-adjust=on,stibp=on,arch-capabilities=on,ssbd=on,xsaves=on,amd-ssbd=on,virt-ssbd=on,svme-addr-chk=on,rdctl-no=on,skip-l1dfl-vmentry=on,mds-no=on,pschange-mc-no=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-kvm.x86_64-7.0.0.args b/tests/qemuxmlconfdata/cpu-host-model-kvm.x86_64-7.0.0.args
index 8f8b1645d5..d6dfadc3b2 100644
--- a/tests/qemuxmlconfdata/cpu-host-model-kvm.x86_64-7.0.0.args
+++ b/tests/qemuxmlconfdata/cpu-host-model-kvm.x86_64-7.0.0.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-q35-7.0,usb=off,dump-guest-core=off,memory-backend=pc.ram \
-accel kvm \
--cpu EPYC-Rome,x2apic=on,tsc-deadline=on,hypervisor=on,tsc-adjust=on,stibp=on,arch-capabilities=on,ssbd=on,xsaves=on,cmp-legacy=on,amd-ssbd=on,virt-ssbd=on,tsc-scale=on,svme-addr-chk=on,rdctl-no=on,skip-l1dfl-vmentry=on,mds-no=on,pschange-mc-no=on \
+-cpu EPYC-Rome,x2apic=on,tsc-deadline=on,hypervisor=on,tsc-adjust=on,stibp=on,arch-capabilities=on,ssbd=on,xsaves=on,amd-ssbd=on,virt-ssbd=on,tsc-scale=on,svme-addr-chk=on,rdctl-no=on,skip-l1dfl-vmentry=on,mds-no=on,pschange-mc-no=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-kvm.x86_64-7.1.0.args b/tests/qemuxmlconfdata/cpu-host-model-kvm.x86_64-7.1.0.args
index df03bafab3..09e220487d 100644
--- a/tests/qemuxmlconfdata/cpu-host-model-kvm.x86_64-7.1.0.args
+++ b/tests/qemuxmlconfdata/cpu-host-model-kvm.x86_64-7.1.0.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-q35-7.1,usb=off,dump-guest-core=off,memory-backend=pc.ram \
-accel kvm \
--cpu EPYC-Rome,x2apic=on,tsc-deadline=on,hypervisor=on,tsc-adjust=on,stibp=on,arch-capabilities=on,ssbd=on,xsaves=on,cmp-legacy=on,amd-ssbd=on,virt-ssbd=on,tsc-scale=on,vmcb-clean=on,svme-addr-chk=on,rdctl-no=on,skip-l1dfl-vmentry=on,mds-no=on,pschange-mc-no=on \
+-cpu EPYC-Rome,x2apic=on,tsc-deadline=on,hypervisor=on,tsc-adjust=on,stibp=on,arch-capabilities=on,ssbd=on,xsaves=on,amd-ssbd=on,virt-ssbd=on,tsc-scale=on,vmcb-clean=on,svme-addr-chk=on,rdctl-no=on,skip-l1dfl-vmentry=on,mds-no=on,pschange-mc-no=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-kvm.x86_64-7.2.0.args b/tests/qemuxmlconfdata/cpu-host-model-kvm.x86_64-7.2.0.args
index 7a796812fa..7e90b309a9 100644
--- a/tests/qemuxmlconfdata/cpu-host-model-kvm.x86_64-7.2.0.args
+++ b/tests/qemuxmlconfdata/cpu-host-model-kvm.x86_64-7.2.0.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-q35-7.2,usb=off,dump-guest-core=off,memory-backend=pc.ram \
-accel kvm \
--cpu EPYC-Rome,x2apic=on,tsc-deadline=on,hypervisor=on,tsc-adjust=on,stibp=on,arch-capabilities=on,ssbd=on,xsaves=on,cmp-legacy=on,amd-ssbd=on,virt-ssbd=on,lbrv=on,tsc-scale=on,vmcb-clean=on,pause-filter=on,pfthreshold=on,v-vmsave-vmload=on,vgif=on,svme-addr-chk=on,rdctl-no=on,skip-l1dfl-vmentry=on,mds-no=on,pschange-mc-no=on \
+-cpu EPYC-Rome,x2apic=on,tsc-deadline=on,hypervisor=on,tsc-adjust=on,stibp=on,arch-capabilities=on,ssbd=on,xsaves=on,amd-ssbd=on,virt-ssbd=on,lbrv=on,tsc-scale=on,vmcb-clean=on,pause-filter=on,pfthreshold=on,v-vmsave-vmload=on,vgif=on,svme-addr-chk=on,rdctl-no=on,skip-l1dfl-vmentry=on,mds-no=on,pschange-mc-no=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-kvm.x86_64-8.0.0.args b/tests/qemuxmlconfdata/cpu-host-model-kvm.x86_64-8.0.0.args
index d63438e81c..fc02c9a7e0 100644
--- a/tests/qemuxmlconfdata/cpu-host-model-kvm.x86_64-8.0.0.args
+++ b/tests/qemuxmlconfdata/cpu-host-model-kvm.x86_64-8.0.0.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-q35-8.0,usb=off,dump-guest-core=off,memory-backend=pc.ram,acpi=off \
-accel kvm \
--cpu EPYC-Rome,x2apic=on,tsc-deadline=on,hypervisor=on,tsc-adjust=on,stibp=on,arch-capabilities=on,ssbd=on,xsaves=on,cmp-legacy=on,amd-ssbd=on,virt-ssbd=on,lbrv=on,tsc-scale=on,vmcb-clean=on,pause-filter=on,pfthreshold=on,v-vmsave-vmload=on,vgif=on,svme-addr-chk=on,rdctl-no=on,skip-l1dfl-vmentry=on,mds-no=on,pschange-mc-no=on \
+-cpu EPYC-Rome,x2apic=on,tsc-deadline=on,hypervisor=on,tsc-adjust=on,stibp=on,arch-capabilities=on,ssbd=on,xsaves=on,amd-ssbd=on,virt-ssbd=on,lbrv=on,tsc-scale=on,vmcb-clean=on,pause-filter=on,pfthreshold=on,v-vmsave-vmload=on,vgif=on,svme-addr-chk=on,rdctl-no=on,skip-l1dfl-vmentry=on,mds-no=on,pschange-mc-no=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-kvm.x86_64-8.1.0.args b/tests/qemuxmlconfdata/cpu-host-model-kvm.x86_64-8.1.0.args
index 901f279a02..8360dc02ef 100644
--- a/tests/qemuxmlconfdata/cpu-host-model-kvm.x86_64-8.1.0.args
+++ b/tests/qemuxmlconfdata/cpu-host-model-kvm.x86_64-8.1.0.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-q35-8.1,usb=off,dump-guest-core=off,memory-backend=pc.ram,acpi=off \
-accel kvm \
--cpu EPYC-Rome,x2apic=on,tsc-deadline=on,hypervisor=on,tsc-adjust=on,stibp=on,arch-capabilities=on,ssbd=on,cmp-legacy=on,amd-ssbd=on,virt-ssbd=on,lbrv=on,tsc-scale=on,vmcb-clean=on,pause-filter=on,pfthreshold=on,v-vmsave-vmload=on,vgif=on,svme-addr-chk=on,lfence-always-serializing=on,null-sel-clr-base=on,rdctl-no=on,skip-l1dfl-vmentry=on,mds-no=on,pschange-mc-no=on,xsaves=off \
+-cpu EPYC-Rome,x2apic=on,tsc-deadline=on,hypervisor=on,tsc-adjust=on,stibp=on,arch-capabilities=on,ssbd=on,amd-ssbd=on,virt-ssbd=on,lbrv=on,tsc-scale=on,vmcb-clean=on,pause-filter=on,pfthreshold=on,v-vmsave-vmload=on,vgif=on,svme-addr-chk=on,lfence-always-serializing=on,null-sel-clr-base=on,rdctl-no=on,skip-l1dfl-vmentry=on,mds-no=on,pschange-mc-no=on,xsaves=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-host-model-kvm.x86_64-8.2.0.args b/tests/qemuxmlconfdata/cpu-host-model-kvm.x86_64-8.2.0.args
index d141aca9f0..b00138933c 100644
--- a/tests/qemuxmlconfdata/cpu-host-model-kvm.x86_64-8.2.0.args
+++ b/tests/qemuxmlconfdata/cpu-host-model-kvm.x86_64-8.2.0.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-q35-8.2,usb=off,dump-guest-core=off,memory-backend=pc.ram,acpi=off \
-accel kvm \
--cpu EPYC-Rome,x2apic=on,tsc-deadline=on,hypervisor=on,tsc-adjust=on,stibp=on,arch-capabilities=on,ssbd=on,cmp-legacy=on,amd-ssbd=on,virt-ssbd=on,lbrv=on,tsc-scale=on,vmcb-clean=on,pause-filter=on,pfthreshold=on,v-vmsave-vmload=on,vgif=on,svme-addr-chk=on,lfence-always-serializing=on,null-sel-clr-base=on,rdctl-no=on,skip-l1dfl-vmentry=on,mds-no=on,pschange-mc-no=on,gds-no=on,xsaves=off \
+-cpu EPYC-Rome,x2apic=on,tsc-deadline=on,hypervisor=on,tsc-adjust=on,stibp=on,arch-capabilities=on,ssbd=on,amd-ssbd=on,virt-ssbd=on,lbrv=on,tsc-scale=on,vmcb-clean=on,pause-filter=on,pfthreshold=on,v-vmsave-vmload=on,vgif=on,svme-addr-chk=on,lfence-always-serializing=on,null-sel-clr-base=on,rdctl-no=on,skip-l1dfl-vmentry=on,mds-no=on,pschange-mc-no=on,gds-no=on,xsaves=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-host-model-kvm.x86_64-9.0.0.args b/tests/qemuxmlconfdata/cpu-host-model-kvm.x86_64-9.0.0.args
index 49575ff4d9..3b42130bd2 100644
--- a/tests/qemuxmlconfdata/cpu-host-model-kvm.x86_64-9.0.0.args
+++ b/tests/qemuxmlconfdata/cpu-host-model-kvm.x86_64-9.0.0.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-q35-9.0,usb=off,dump-guest-core=off,memory-backend=pc.ram,acpi=off \
-accel kvm \
--cpu EPYC-Rome,x2apic=on,tsc-deadline=on,hypervisor=on,tsc-adjust=on,stibp=on,arch-capabilities=on,ssbd=on,cmp-legacy=on,amd-ssbd=on,virt-ssbd=on,lbrv=on,tsc-scale=on,vmcb-clean=on,pause-filter=on,pfthreshold=on,v-vmsave-vmload=on,vgif=on,svme-addr-chk=on,lfence-always-serializing=on,null-sel-clr-base=on,rdctl-no=on,skip-l1dfl-vmentry=on,mds-no=on,pschange-mc-no=on,gds-no=on,xsaves=off \
+-cpu EPYC-Rome,x2apic=on,tsc-deadline=on,hypervisor=on,tsc-adjust=on,stibp=on,arch-capabilities=on,ssbd=on,amd-ssbd=on,virt-ssbd=on,lbrv=on,tsc-scale=on,vmcb-clean=on,pause-filter=on,pfthreshold=on,v-vmsave-vmload=on,vgif=on,svme-addr-chk=on,lfence-always-serializing=on,null-sel-clr-base=on,rdctl-no=on,skip-l1dfl-vmentry=on,mds-no=on,pschange-mc-no=on,gds-no=on,xsaves=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-host-model-kvm.x86_64-9.1.0.args b/tests/qemuxmlconfdata/cpu-host-model-kvm.x86_64-9.1.0.args
index fd25e4cd23..c451426cdd 100644
--- a/tests/qemuxmlconfdata/cpu-host-model-kvm.x86_64-9.1.0.args
+++ b/tests/qemuxmlconfdata/cpu-host-model-kvm.x86_64-9.1.0.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-q35-9.1,usb=off,dump-guest-core=off,memory-backend=pc.ram,acpi=off \
-accel kvm \
--cpu EPYC-Rome,x2apic=on,tsc-deadline=on,hypervisor=on,tsc-adjust=on,stibp=on,arch-capabilities=on,ssbd=on,cmp-legacy=on,overflow-recov=on,succor=on,amd-ssbd=on,virt-ssbd=on,lbrv=on,tsc-scale=on,vmcb-clean=on,flushbyasid=on,pause-filter=on,pfthreshold=on,v-vmsave-vmload=on,vgif=on,svme-addr-chk=on,lfence-always-serializing=on,null-sel-clr-base=on,rdctl-no=on,skip-l1dfl-vmentry=on,mds-no=on,pschange-mc-no=on,gds-no=on,rfds-no=on,xsaves=off \
+-cpu EPYC-Rome,x2apic=on,tsc-deadline=on,hypervisor=on,tsc-adjust=on,stibp=on,arch-capabilities=on,ssbd=on,overflow-recov=on,succor=on,amd-ssbd=on,virt-ssbd=on,lbrv=on,tsc-scale=on,vmcb-clean=on,flushbyasid=on,pause-filter=on,pfthreshold=on,v-vmsave-vmload=on,vgif=on,svme-addr-chk=on,lfence-always-serializing=on,null-sel-clr-base=on,rdctl-no=on,skip-l1dfl-vmentry=on,mds-no=on,pschange-mc-no=on,gds-no=on,rfds-no=on,xsaves=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-host-model-kvm.x86_64-9.2.0.args b/tests/qemuxmlconfdata/cpu-host-model-kvm.x86_64-9.2.0.args
index 4b69f59064..1da6e508ff 100644
--- a/tests/qemuxmlconfdata/cpu-host-model-kvm.x86_64-9.2.0.args
+++ b/tests/qemuxmlconfdata/cpu-host-model-kvm.x86_64-9.2.0.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-q35-9.2,usb=off,dump-guest-core=off,memory-backend=pc.ram,acpi=off \
-accel kvm \
--cpu EPYC-Rome,x2apic=on,tsc-deadline=on,hypervisor=on,tsc-adjust=on,stibp=on,arch-capabilities=on,ssbd=on,cmp-legacy=on,overflow-recov=on,succor=on,amd-ssbd=on,virt-ssbd=on,lbrv=on,tsc-scale=on,vmcb-clean=on,flushbyasid=on,pause-filter=on,pfthreshold=on,v-vmsave-vmload=on,vgif=on,svme-addr-chk=on,lfence-always-serializing=on,null-sel-clr-base=on,ibpb-brtype=on,rdctl-no=on,skip-l1dfl-vmentry=on,mds-no=on,pschange-mc-no=on,gds-no=on,rfds-no=on,xsaves=off \
+-cpu EPYC-Rome,x2apic=on,tsc-deadline=on,hypervisor=on,tsc-adjust=on,stibp=on,arch-capabilities=on,ssbd=on,overflow-recov=on,succor=on,amd-ssbd=on,virt-ssbd=on,lbrv=on,tsc-scale=on,vmcb-clean=on,flushbyasid=on,pause-filter=on,pfthreshold=on,v-vmsave-vmload=on,vgif=on,svme-addr-chk=on,lfence-always-serializing=on,null-sel-clr-base=on,ibpb-brtype=on,rdctl-no=on,skip-l1dfl-vmentry=on,mds-no=on,pschange-mc-no=on,gds-no=on,rfds-no=on,xsaves=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-host-model-kvm.x86_64-latest.args b/tests/qemuxmlconfdata/cpu-host-model-kvm.x86_64-latest.args
index 2bf920b9c7..30010edb3b 100644
--- a/tests/qemuxmlconfdata/cpu-host-model-kvm.x86_64-latest.args
+++ b/tests/qemuxmlconfdata/cpu-host-model-kvm.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 q35,usb=off,dump-guest-core=off,memory-backend=pc.ram,acpi=off \
-accel kvm \
--cpu EPYC-Turin,x2apic=on,tsc-deadline=on,hypervisor=on,tsc-adjust=on,spec-ctrl=on,stibp=on,flush-l1d=on,ssbd=on,cmp-legacy=on,virt-ssbd=on,tsa-sq-no=on,tsa-l1-no=on,pcid=off,la57=off \
+-cpu EPYC-Turin,x2apic=on,tsc-deadline=on,hypervisor=on,tsc-adjust=on,spec-ctrl=on,stibp=on,flush-l1d=on,ssbd=on,virt-ssbd=on,tsa-sq-no=on,tsa-l1-no=on,pcid=off,la57=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-host-model-nofallback-kvm.x86_64-10.0.0.args b/tests/qemuxmlconfdata/cpu-host-model-nofallback-kvm.x86_64-10.0.0.args
index edd334dd8b..08f37274b2 100644
--- a/tests/qemuxmlconfdata/cpu-host-model-nofallback-kvm.x86_64-10.0.0.args
+++ b/tests/qemuxmlconfdata/cpu-host-model-nofallback-kvm.x86_64-10.0.0.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-i440fx-10.0,usb=off,dump-guest-core=off,memory-backend=pc.ram,acpi=off \
-accel kvm \
--cpu EPYC-Rome,x2apic=on,tsc-deadline=on,hypervisor=on,tsc-adjust=on,stibp=on,arch-capabilities=on,ssbd=on,cmp-legacy=on,overflow-recov=on,succor=on,amd-ssbd=on,virt-ssbd=on,lbrv=on,tsc-scale=on,vmcb-clean=on,flushbyasid=on,pause-filter=on,pfthreshold=on,v-vmsave-vmload=on,vgif=on,svme-addr-chk=on,lfence-always-serializing=on,null-sel-clr-base=on,ibpb-brtype=on,rdctl-no=on,skip-l1dfl-vmentry=on,mds-no=on,pschange-mc-no=on,gds-no=on,rfds-no=on,xsaves=off \
+-cpu EPYC-Rome,x2apic=on,tsc-deadline=on,hypervisor=on,tsc-adjust=on,stibp=on,arch-capabilities=on,ssbd=on,overflow-recov=on,succor=on,amd-ssbd=on,virt-ssbd=on,lbrv=on,tsc-scale=on,vmcb-clean=on,flushbyasid=on,pause-filter=on,pfthreshold=on,v-vmsave-vmload=on,vgif=on,svme-addr-chk=on,lfence-always-serializing=on,null-sel-clr-base=on,ibpb-brtype=on,rdctl-no=on,skip-l1dfl-vmentry=on,mds-no=on,pschange-mc-no=on,gds-no=on,rfds-no=on,xsaves=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-host-model-nofallback-kvm.x86_64-10.1.0.args b/tests/qemuxmlconfdata/cpu-host-model-nofallback-kvm.x86_64-10.1.0.args
index 57982574eb..e4044a0c64 100644
--- a/tests/qemuxmlconfdata/cpu-host-model-nofallback-kvm.x86_64-10.1.0.args
+++ b/tests/qemuxmlconfdata/cpu-host-model-nofallback-kvm.x86_64-10.1.0.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-i440fx-10.1,usb=off,dump-guest-core=off,memory-backend=pc.ram,acpi=off \
-accel kvm \
--cpu EPYC-Rome,x2apic=on,tsc-deadline=on,hypervisor=on,tsc-adjust=on,stibp=on,ssbd=on,cmp-legacy=on,overflow-recov=on,succor=on,amd-ssbd=on,virt-ssbd=on,lbrv=on,tsc-scale=on,vmcb-clean=on,flushbyasid=on,pause-filter=on,pfthreshold=on,v-vmsave-vmload=on,vgif=on,svme-addr-chk=on,lfence-always-serializing=on,null-sel-clr-base=on,ibpb-brtype=on,xsaves=off \
+-cpu EPYC-Rome,x2apic=on,tsc-deadline=on,hypervisor=on,tsc-adjust=on,stibp=on,ssbd=on,overflow-recov=on,succor=on,amd-ssbd=on,virt-ssbd=on,lbrv=on,tsc-scale=on,vmcb-clean=on,flushbyasid=on,pause-filter=on,pfthreshold=on,v-vmsave-vmload=on,vgif=on,svme-addr-chk=on,lfence-always-serializing=on,null-sel-clr-base=on,ibpb-brtype=on,xsaves=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-host-model-nofallback-kvm.x86_64-6.2.0.args b/tests/qemuxmlconfdata/cpu-host-model-nofallback-kvm.x86_64-6.2.0.args
index 4aa9011fe8..e8a9aceb4a 100644
--- a/tests/qemuxmlconfdata/cpu-host-model-nofallback-kvm.x86_64-6.2.0.args
+++ b/tests/qemuxmlconfdata/cpu-host-model-nofallback-kvm.x86_64-6.2.0.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-i440fx-6.2,usb=off,dump-guest-core=off,memory-backend=pc.ram \
-accel kvm \
--cpu EPYC-Rome,x2apic=on,tsc-deadline=on,hypervisor=on,tsc-adjust=on,stibp=on,arch-capabilities=on,ssbd=on,xsaves=on,cmp-legacy=on,amd-ssbd=on,virt-ssbd=on,svme-addr-chk=on,rdctl-no=on,skip-l1dfl-vmentry=on,mds-no=on,pschange-mc-no=on \
+-cpu EPYC-Rome,x2apic=on,tsc-deadline=on,hypervisor=on,tsc-adjust=on,stibp=on,arch-capabilities=on,ssbd=on,xsaves=on,amd-ssbd=on,virt-ssbd=on,svme-addr-chk=on,rdctl-no=on,skip-l1dfl-vmentry=on,mds-no=on,pschange-mc-no=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-nofallback-kvm.x86_64-7.0.0.args b/tests/qemuxmlconfdata/cpu-host-model-nofallback-kvm.x86_64-7.0.0.args
index e944e69cfd..0df6ce9e3d 100644
--- a/tests/qemuxmlconfdata/cpu-host-model-nofallback-kvm.x86_64-7.0.0.args
+++ b/tests/qemuxmlconfdata/cpu-host-model-nofallback-kvm.x86_64-7.0.0.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-i440fx-7.0,usb=off,dump-guest-core=off,memory-backend=pc.ram \
-accel kvm \
--cpu EPYC-Rome,x2apic=on,tsc-deadline=on,hypervisor=on,tsc-adjust=on,stibp=on,arch-capabilities=on,ssbd=on,xsaves=on,cmp-legacy=on,amd-ssbd=on,virt-ssbd=on,tsc-scale=on,svme-addr-chk=on,rdctl-no=on,skip-l1dfl-vmentry=on,mds-no=on,pschange-mc-no=on \
+-cpu EPYC-Rome,x2apic=on,tsc-deadline=on,hypervisor=on,tsc-adjust=on,stibp=on,arch-capabilities=on,ssbd=on,xsaves=on,amd-ssbd=on,virt-ssbd=on,tsc-scale=on,svme-addr-chk=on,rdctl-no=on,skip-l1dfl-vmentry=on,mds-no=on,pschange-mc-no=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-nofallback-kvm.x86_64-7.1.0.args b/tests/qemuxmlconfdata/cpu-host-model-nofallback-kvm.x86_64-7.1.0.args
index d9edda2733..b4a91fa921 100644
--- a/tests/qemuxmlconfdata/cpu-host-model-nofallback-kvm.x86_64-7.1.0.args
+++ b/tests/qemuxmlconfdata/cpu-host-model-nofallback-kvm.x86_64-7.1.0.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-i440fx-7.1,usb=off,dump-guest-core=off,memory-backend=pc.ram \
-accel kvm \
--cpu EPYC-Rome,x2apic=on,tsc-deadline=on,hypervisor=on,tsc-adjust=on,stibp=on,arch-capabilities=on,ssbd=on,xsaves=on,cmp-legacy=on,amd-ssbd=on,virt-ssbd=on,tsc-scale=on,vmcb-clean=on,svme-addr-chk=on,rdctl-no=on,skip-l1dfl-vmentry=on,mds-no=on,pschange-mc-no=on \
+-cpu EPYC-Rome,x2apic=on,tsc-deadline=on,hypervisor=on,tsc-adjust=on,stibp=on,arch-capabilities=on,ssbd=on,xsaves=on,amd-ssbd=on,virt-ssbd=on,tsc-scale=on,vmcb-clean=on,svme-addr-chk=on,rdctl-no=on,skip-l1dfl-vmentry=on,mds-no=on,pschange-mc-no=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-nofallback-kvm.x86_64-7.2.0.args b/tests/qemuxmlconfdata/cpu-host-model-nofallback-kvm.x86_64-7.2.0.args
index 1d1839b7fa..5d69199876 100644
--- a/tests/qemuxmlconfdata/cpu-host-model-nofallback-kvm.x86_64-7.2.0.args
+++ b/tests/qemuxmlconfdata/cpu-host-model-nofallback-kvm.x86_64-7.2.0.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-i440fx-7.2,usb=off,dump-guest-core=off,memory-backend=pc.ram \
-accel kvm \
--cpu EPYC-Rome,x2apic=on,tsc-deadline=on,hypervisor=on,tsc-adjust=on,stibp=on,arch-capabilities=on,ssbd=on,xsaves=on,cmp-legacy=on,amd-ssbd=on,virt-ssbd=on,lbrv=on,tsc-scale=on,vmcb-clean=on,pause-filter=on,pfthreshold=on,v-vmsave-vmload=on,vgif=on,svme-addr-chk=on,rdctl-no=on,skip-l1dfl-vmentry=on,mds-no=on,pschange-mc-no=on \
+-cpu EPYC-Rome,x2apic=on,tsc-deadline=on,hypervisor=on,tsc-adjust=on,stibp=on,arch-capabilities=on,ssbd=on,xsaves=on,amd-ssbd=on,virt-ssbd=on,lbrv=on,tsc-scale=on,vmcb-clean=on,pause-filter=on,pfthreshold=on,v-vmsave-vmload=on,vgif=on,svme-addr-chk=on,rdctl-no=on,skip-l1dfl-vmentry=on,mds-no=on,pschange-mc-no=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-nofallback-kvm.x86_64-8.0.0.args b/tests/qemuxmlconfdata/cpu-host-model-nofallback-kvm.x86_64-8.0.0.args
index 8278629ee7..e7b424819e 100644
--- a/tests/qemuxmlconfdata/cpu-host-model-nofallback-kvm.x86_64-8.0.0.args
+++ b/tests/qemuxmlconfdata/cpu-host-model-nofallback-kvm.x86_64-8.0.0.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-i440fx-8.0,usb=off,dump-guest-core=off,memory-backend=pc.ram,acpi=off \
-accel kvm \
--cpu EPYC-Rome,x2apic=on,tsc-deadline=on,hypervisor=on,tsc-adjust=on,stibp=on,arch-capabilities=on,ssbd=on,xsaves=on,cmp-legacy=on,amd-ssbd=on,virt-ssbd=on,lbrv=on,tsc-scale=on,vmcb-clean=on,pause-filter=on,pfthreshold=on,v-vmsave-vmload=on,vgif=on,svme-addr-chk=on,rdctl-no=on,skip-l1dfl-vmentry=on,mds-no=on,pschange-mc-no=on \
+-cpu EPYC-Rome,x2apic=on,tsc-deadline=on,hypervisor=on,tsc-adjust=on,stibp=on,arch-capabilities=on,ssbd=on,xsaves=on,amd-ssbd=on,virt-ssbd=on,lbrv=on,tsc-scale=on,vmcb-clean=on,pause-filter=on,pfthreshold=on,v-vmsave-vmload=on,vgif=on,svme-addr-chk=on,rdctl-no=on,skip-l1dfl-vmentry=on,mds-no=on,pschange-mc-no=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-nofallback-kvm.x86_64-8.1.0.args b/tests/qemuxmlconfdata/cpu-host-model-nofallback-kvm.x86_64-8.1.0.args
index 3b733a3c5d..58ad565dba 100644
--- a/tests/qemuxmlconfdata/cpu-host-model-nofallback-kvm.x86_64-8.1.0.args
+++ b/tests/qemuxmlconfdata/cpu-host-model-nofallback-kvm.x86_64-8.1.0.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-i440fx-8.1,usb=off,dump-guest-core=off,memory-backend=pc.ram,acpi=off \
-accel kvm \
--cpu EPYC-Rome,x2apic=on,tsc-deadline=on,hypervisor=on,tsc-adjust=on,stibp=on,arch-capabilities=on,ssbd=on,cmp-legacy=on,amd-ssbd=on,virt-ssbd=on,lbrv=on,tsc-scale=on,vmcb-clean=on,pause-filter=on,pfthreshold=on,v-vmsave-vmload=on,vgif=on,svme-addr-chk=on,lfence-always-serializing=on,null-sel-clr-base=on,rdctl-no=on,skip-l1dfl-vmentry=on,mds-no=on,pschange-mc-no=on,xsaves=off \
+-cpu EPYC-Rome,x2apic=on,tsc-deadline=on,hypervisor=on,tsc-adjust=on,stibp=on,arch-capabilities=on,ssbd=on,amd-ssbd=on,virt-ssbd=on,lbrv=on,tsc-scale=on,vmcb-clean=on,pause-filter=on,pfthreshold=on,v-vmsave-vmload=on,vgif=on,svme-addr-chk=on,lfence-always-serializing=on,null-sel-clr-base=on,rdctl-no=on,skip-l1dfl-vmentry=on,mds-no=on,pschange-mc-no=on,xsaves=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-host-model-nofallback-kvm.x86_64-8.2.0.args b/tests/qemuxmlconfdata/cpu-host-model-nofallback-kvm.x86_64-8.2.0.args
index 73296c7df0..fa1b674fa5 100644
--- a/tests/qemuxmlconfdata/cpu-host-model-nofallback-kvm.x86_64-8.2.0.args
+++ b/tests/qemuxmlconfdata/cpu-host-model-nofallback-kvm.x86_64-8.2.0.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-i440fx-8.2,usb=off,dump-guest-core=off,memory-backend=pc.ram,acpi=off \
-accel kvm \
--cpu EPYC-Rome,x2apic=on,tsc-deadline=on,hypervisor=on,tsc-adjust=on,stibp=on,arch-capabilities=on,ssbd=on,cmp-legacy=on,amd-ssbd=on,virt-ssbd=on,lbrv=on,tsc-scale=on,vmcb-clean=on,pause-filter=on,pfthreshold=on,v-vmsave-vmload=on,vgif=on,svme-addr-chk=on,lfence-always-serializing=on,null-sel-clr-base=on,rdctl-no=on,skip-l1dfl-vmentry=on,mds-no=on,pschange-mc-no=on,gds-no=on,xsaves=off \
+-cpu EPYC-Rome,x2apic=on,tsc-deadline=on,hypervisor=on,tsc-adjust=on,stibp=on,arch-capabilities=on,ssbd=on,amd-ssbd=on,virt-ssbd=on,lbrv=on,tsc-scale=on,vmcb-clean=on,pause-filter=on,pfthreshold=on,v-vmsave-vmload=on,vgif=on,svme-addr-chk=on,lfence-always-serializing=on,null-sel-clr-base=on,rdctl-no=on,skip-l1dfl-vmentry=on,mds-no=on,pschange-mc-no=on,gds-no=on,xsaves=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-host-model-nofallback-kvm.x86_64-9.0.0.args b/tests/qemuxmlconfdata/cpu-host-model-nofallback-kvm.x86_64-9.0.0.args
index 8f8b74fa56..fc9985f901 100644
--- a/tests/qemuxmlconfdata/cpu-host-model-nofallback-kvm.x86_64-9.0.0.args
+++ b/tests/qemuxmlconfdata/cpu-host-model-nofallback-kvm.x86_64-9.0.0.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-i440fx-9.0,usb=off,dump-guest-core=off,memory-backend=pc.ram,acpi=off \
-accel kvm \
--cpu EPYC-Rome,x2apic=on,tsc-deadline=on,hypervisor=on,tsc-adjust=on,stibp=on,arch-capabilities=on,ssbd=on,cmp-legacy=on,amd-ssbd=on,virt-ssbd=on,lbrv=on,tsc-scale=on,vmcb-clean=on,pause-filter=on,pfthreshold=on,v-vmsave-vmload=on,vgif=on,svme-addr-chk=on,lfence-always-serializing=on,null-sel-clr-base=on,rdctl-no=on,skip-l1dfl-vmentry=on,mds-no=on,pschange-mc-no=on,gds-no=on,xsaves=off \
+-cpu EPYC-Rome,x2apic=on,tsc-deadline=on,hypervisor=on,tsc-adjust=on,stibp=on,arch-capabilities=on,ssbd=on,amd-ssbd=on,virt-ssbd=on,lbrv=on,tsc-scale=on,vmcb-clean=on,pause-filter=on,pfthreshold=on,v-vmsave-vmload=on,vgif=on,svme-addr-chk=on,lfence-always-serializing=on,null-sel-clr-base=on,rdctl-no=on,skip-l1dfl-vmentry=on,mds-no=on,pschange-mc-no=on,gds-no=on,xsaves=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-host-model-nofallback-kvm.x86_64-9.1.0.args b/tests/qemuxmlconfdata/cpu-host-model-nofallback-kvm.x86_64-9.1.0.args
index c2f394bf09..1db86cb31e 100644
--- a/tests/qemuxmlconfdata/cpu-host-model-nofallback-kvm.x86_64-9.1.0.args
+++ b/tests/qemuxmlconfdata/cpu-host-model-nofallback-kvm.x86_64-9.1.0.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-i440fx-9.1,usb=off,dump-guest-core=off,memory-backend=pc.ram,acpi=off \
-accel kvm \
--cpu EPYC-Rome,x2apic=on,tsc-deadline=on,hypervisor=on,tsc-adjust=on,stibp=on,arch-capabilities=on,ssbd=on,cmp-legacy=on,overflow-recov=on,succor=on,amd-ssbd=on,virt-ssbd=on,lbrv=on,tsc-scale=on,vmcb-clean=on,flushbyasid=on,pause-filter=on,pfthreshold=on,v-vmsave-vmload=on,vgif=on,svme-addr-chk=on,lfence-always-serializing=on,null-sel-clr-base=on,rdctl-no=on,skip-l1dfl-vmentry=on,mds-no=on,pschange-mc-no=on,gds-no=on,rfds-no=on,xsaves=off \
+-cpu EPYC-Rome,x2apic=on,tsc-deadline=on,hypervisor=on,tsc-adjust=on,stibp=on,arch-capabilities=on,ssbd=on,overflow-recov=on,succor=on,amd-ssbd=on,virt-ssbd=on,lbrv=on,tsc-scale=on,vmcb-clean=on,flushbyasid=on,pause-filter=on,pfthreshold=on,v-vmsave-vmload=on,vgif=on,svme-addr-chk=on,lfence-always-serializing=on,null-sel-clr-base=on,rdctl-no=on,skip-l1dfl-vmentry=on,mds-no=on,pschange-mc-no=on,gds-no=on,rfds-no=on,xsaves=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-host-model-nofallback-kvm.x86_64-9.2.0.args b/tests/qemuxmlconfdata/cpu-host-model-nofallback-kvm.x86_64-9.2.0.args
index 35c8d397c4..4dcd9332cb 100644
--- a/tests/qemuxmlconfdata/cpu-host-model-nofallback-kvm.x86_64-9.2.0.args
+++ b/tests/qemuxmlconfdata/cpu-host-model-nofallback-kvm.x86_64-9.2.0.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-i440fx-9.2,usb=off,dump-guest-core=off,memory-backend=pc.ram,acpi=off \
-accel kvm \
--cpu EPYC-Rome,x2apic=on,tsc-deadline=on,hypervisor=on,tsc-adjust=on,stibp=on,arch-capabilities=on,ssbd=on,cmp-legacy=on,overflow-recov=on,succor=on,amd-ssbd=on,virt-ssbd=on,lbrv=on,tsc-scale=on,vmcb-clean=on,flushbyasid=on,pause-filter=on,pfthreshold=on,v-vmsave-vmload=on,vgif=on,svme-addr-chk=on,lfence-always-serializing=on,null-sel-clr-base=on,ibpb-brtype=on,rdctl-no=on,skip-l1dfl-vmentry=on,mds-no=on,pschange-mc-no=on,gds-no=on,rfds-no=on,xsaves=off \
+-cpu EPYC-Rome,x2apic=on,tsc-deadline=on,hypervisor=on,tsc-adjust=on,stibp=on,arch-capabilities=on,ssbd=on,overflow-recov=on,succor=on,amd-ssbd=on,virt-ssbd=on,lbrv=on,tsc-scale=on,vmcb-clean=on,flushbyasid=on,pause-filter=on,pfthreshold=on,v-vmsave-vmload=on,vgif=on,svme-addr-chk=on,lfence-always-serializing=on,null-sel-clr-base=on,ibpb-brtype=on,rdctl-no=on,skip-l1dfl-vmentry=on,mds-no=on,pschange-mc-no=on,gds-no=on,rfds-no=on,xsaves=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-host-model-nofallback-kvm.x86_64-latest.args b/tests/qemuxmlconfdata/cpu-host-model-nofallback-kvm.x86_64-latest.args
index 6afa8a4c2d..e5b0acb87b 100644
--- a/tests/qemuxmlconfdata/cpu-host-model-nofallback-kvm.x86_64-latest.args
+++ b/tests/qemuxmlconfdata/cpu-host-model-nofallback-kvm.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 EPYC-Turin,x2apic=on,tsc-deadline=on,hypervisor=on,tsc-adjust=on,spec-ctrl=on,stibp=on,flush-l1d=on,ssbd=on,cmp-legacy=on,virt-ssbd=on,tsa-sq-no=on,tsa-l1-no=on,pcid=off,la57=off \
+-cpu EPYC-Turin,x2apic=on,tsc-deadline=on,hypervisor=on,tsc-adjust=on,spec-ctrl=on,stibp=on,flush-l1d=on,ssbd=on,virt-ssbd=on,tsa-sq-no=on,tsa-l1-no=on,pcid=off,la57=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-host-model-nofallback-tcg.x86_64-10.1.0.args b/tests/qemuxmlconfdata/cpu-host-model-nofallback-tcg.x86_64-10.1.0.args
index 3b93ed510d..0b67c7f158 100644
--- a/tests/qemuxmlconfdata/cpu-host-model-nofallback-tcg.x86_64-10.1.0.args
+++ b/tests/qemuxmlconfdata/cpu-host-model-nofallback-tcg.x86_64-10.1.0.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-i440fx-10.1,usb=off,dump-guest-core=off,memory-backend=pc.ram,acpi=off \
-accel tcg \
--cpu EPYC,monitor=on,x2apic=on,hypervisor=on,acpi=on,ss=on,erms=on,mpx=on,clwb=on,umip=on,pku=on,vaes=on,la57=on,rdpid=on,pks=on,fsrm=on,cmpccxadd=on,fzrm=on,fsrs=on,fsrc=on,cmp-legacy=on,3dnowext=on,3dnow=on,xsaveerptr=on,wbnoinvd=on,npt=on,vgif=on,svme-addr-chk=on,no-nested-data-bp=on,null-sel-clr-base=on,vme=off,xsavec=off,misalignsse=off,osvw=off,topoext=off,fxsr-opt=off,nrip-save=off \
+-cpu EPYC,monitor=on,x2apic=on,hypervisor=on,acpi=on,ss=on,erms=on,mpx=on,clwb=on,umip=on,pku=on,vaes=on,la57=on,rdpid=on,pks=on,fsrm=on,cmpccxadd=on,fzrm=on,fsrs=on,fsrc=on,3dnowext=on,3dnow=on,xsaveerptr=on,wbnoinvd=on,npt=on,vgif=on,svme-addr-chk=on,no-nested-data-bp=on,null-sel-clr-base=on,vme=off,xsavec=off,misalignsse=off,osvw=off,topoext=off,fxsr-opt=off,nrip-save=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-host-model-nofallback-tcg.x86_64-latest.args b/tests/qemuxmlconfdata/cpu-host-model-nofallback-tcg.x86_64-latest.args
index 01cf90bb67..443de62f69 100644
--- a/tests/qemuxmlconfdata/cpu-host-model-nofallback-tcg.x86_64-latest.args
+++ b/tests/qemuxmlconfdata/cpu-host-model-nofallback-tcg.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 EPYC,monitor=on,x2apic=on,hypervisor=on,acpi=on,ss=on,erms=on,mpx=on,clwb=on,umip=on,pku=on,vaes=on,la57=on,rdpid=on,pks=on,fsrm=on,cmpccxadd=on,fzrm=on,fsrs=on,fsrc=on,cmp-legacy=on,3dnowext=on,3dnow=on,xsaveerptr=on,wbnoinvd=on,npt=on,vgif=on,svme-addr-chk=on,no-nested-data-bp=on,null-sel-clr-base=on,vme=off,xsavec=off,misalignsse=off,osvw=off,topoext=off,fxsr-opt=off,nrip-save=off \
+-cpu EPYC,monitor=on,x2apic=on,hypervisor=on,acpi=on,ss=on,erms=on,mpx=on,clwb=on,umip=on,pku=on,vaes=on,la57=on,rdpid=on,pks=on,fsrm=on,cmpccxadd=on,fzrm=on,fsrs=on,fsrc=on,3dnowext=on,3dnow=on,xsaveerptr=on,wbnoinvd=on,npt=on,vgif=on,svme-addr-chk=on,no-nested-data-bp=on,null-sel-clr-base=on,vme=off,xsavec=off,misalignsse=off,osvw=off,topoext=off,fxsr-opt=off,nrip-save=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-host-model-tcg.x86_64-10.1.0.args b/tests/qemuxmlconfdata/cpu-host-model-tcg.x86_64-10.1.0.args
index 4defeceac3..d12cb96786 100644
--- a/tests/qemuxmlconfdata/cpu-host-model-tcg.x86_64-10.1.0.args
+++ b/tests/qemuxmlconfdata/cpu-host-model-tcg.x86_64-10.1.0.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-q35-10.1,usb=off,dump-guest-core=off,memory-backend=pc.ram,acpi=off \
-accel tcg \
--cpu EPYC,monitor=on,x2apic=on,hypervisor=on,acpi=on,ss=on,erms=on,mpx=on,clwb=on,umip=on,pku=on,vaes=on,la57=on,rdpid=on,pks=on,fsrm=on,cmpccxadd=on,fzrm=on,fsrs=on,fsrc=on,cmp-legacy=on,3dnowext=on,3dnow=on,xsaveerptr=on,wbnoinvd=on,npt=on,vgif=on,svme-addr-chk=on,no-nested-data-bp=on,null-sel-clr-base=on,vme=off,xsavec=off,misalignsse=off,osvw=off,topoext=off,fxsr-opt=off,nrip-save=off \
+-cpu EPYC,monitor=on,x2apic=on,hypervisor=on,acpi=on,ss=on,erms=on,mpx=on,clwb=on,umip=on,pku=on,vaes=on,la57=on,rdpid=on,pks=on,fsrm=on,cmpccxadd=on,fzrm=on,fsrs=on,fsrc=on,3dnowext=on,3dnow=on,xsaveerptr=on,wbnoinvd=on,npt=on,vgif=on,svme-addr-chk=on,no-nested-data-bp=on,null-sel-clr-base=on,vme=off,xsavec=off,misalignsse=off,osvw=off,topoext=off,fxsr-opt=off,nrip-save=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-host-model-tcg.x86_64-latest.args b/tests/qemuxmlconfdata/cpu-host-model-tcg.x86_64-latest.args
index 479266659a..688a217c3c 100644
--- a/tests/qemuxmlconfdata/cpu-host-model-tcg.x86_64-latest.args
+++ b/tests/qemuxmlconfdata/cpu-host-model-tcg.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 q35,usb=off,dump-guest-core=off,memory-backend=pc.ram,acpi=off \
-accel tcg \
--cpu EPYC,monitor=on,x2apic=on,hypervisor=on,acpi=on,ss=on,erms=on,mpx=on,clwb=on,umip=on,pku=on,vaes=on,la57=on,rdpid=on,pks=on,fsrm=on,cmpccxadd=on,fzrm=on,fsrs=on,fsrc=on,cmp-legacy=on,3dnowext=on,3dnow=on,xsaveerptr=on,wbnoinvd=on,npt=on,vgif=on,svme-addr-chk=on,no-nested-data-bp=on,null-sel-clr-base=on,vme=off,xsavec=off,misalignsse=off,osvw=off,topoext=off,fxsr-opt=off,nrip-save=off \
+-cpu EPYC,monitor=on,x2apic=on,hypervisor=on,acpi=on,ss=on,erms=on,mpx=on,clwb=on,umip=on,pku=on,vaes=on,la57=on,rdpid=on,pks=on,fsrm=on,cmpccxadd=on,fzrm=on,fsrs=on,fsrc=on,3dnowext=on,3dnow=on,xsaveerptr=on,wbnoinvd=on,npt=on,vgif=on,svme-addr-chk=on,no-nested-data-bp=on,null-sel-clr-base=on,vme=off,xsavec=off,misalignsse=off,osvw=off,topoext=off,fxsr-opt=off,nrip-save=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-translation.x86_64-latest.args b/tests/qemuxmlconfdata/cpu-translation.x86_64-latest.args
index 49e1b590dd..d425866c67 100644
--- a/tests/qemuxmlconfdata/cpu-translation.x86_64-latest.args
+++ b/tests/qemuxmlconfdata/cpu-translation.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,pclmulqdq=on,ds-cpl=on,tsc-adjust=on,fxsr-opt=on,lahf-lm=on,cmp-legacy=on,nodeid-msr=on,perfctr-core=on,perfctr-nb=on,kvm-pv-eoi=on,kvm-pv-unhalt=on \
+-cpu Haswell,pclmulqdq=on,ds-cpl=on,tsc-adjust=on,fxsr-opt=on,lahf-lm=on,nodeid-msr=on,perfctr-core=on,perfctr-nb=on,kvm-pv-eoi=on,kvm-pv-unhalt=on \
-m size=219136k \
-object '{"qom-type":"memory-backend-ram","id":"pc.ram","size":224395264}' \
-overcommit mem-lock=off \
--
2.53.0

View File

@ -0,0 +1,191 @@
From bb8ef43213cb1f8c123cdcc693d99a30b09dfa16 Mon Sep 17 00:00:00 2001
Message-ID: <bb8ef43213cb1f8c123cdcc693d99a30b09dfa16.1770383182.git.jdenemar@redhat.com>
From: Nathan Chen <nathanc@nvidia.com>
Date: Fri, 30 Jan 2026 10:59:12 -0800
Subject: [PATCH] qemu: Implement support for associating iommufd to hostdev
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Implement a new iommufd attribute under hostdevs' PCI
subsystem driver that can be used to specify associated
iommufd object when launching a qemu VM.
Signed-off-by: Ján Tomko <jtomko@redhat.com>
Signed-off-by: Nathan Chen <nathanc@nvidia.com>
Reviewed-by: Pavel Hrdina <phrdina@redhat.com>
(cherry picked from commit fd113055bb174c7284081731d16959f73796e3d7)
Resolves: https://issues.redhat.com/browse/RHEL-74202
Resolves: https://issues.redhat.com/browse/RHEL-126346
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
---
docs/formatdomain.rst | 6 +++++
src/conf/device_conf.c | 11 ++++++++
src/conf/device_conf.h | 1 +
src/conf/schemas/basictypes.rng | 5 ++++
src/qemu/qemu_command.c | 46 +++++++++++++++++++++++++++++++++
5 files changed, 69 insertions(+)
diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst
index 1467fc7e10..167912348e 100644
--- a/docs/formatdomain.rst
+++ b/docs/formatdomain.rst
@@ -4907,6 +4907,12 @@ or:
found is "problematic" in some way, the generic vfio-pci driver
similarly be forced.
+ :since:`Since 12.1.0 (QEMU and KVM only)`, the ``iommufd`` element
+ can be used to enable IOMMUFD backend for VFIO device. This
+ provides an interface to propagate DMA mappings to kernel for
+ assigned devices. Libvirt will open the /dev/iommu and VFIO device
+ cdev and pass associated file descriptors to QEMU.
+
(Note: :since:`Since 1.0.5`, the ``name`` attribute has been
described to be used to select the type of PCI device assignment
("vfio", "kvm", or "xen"), but those values have been mostly
diff --git a/src/conf/device_conf.c b/src/conf/device_conf.c
index c278b81652..d68232a4f4 100644
--- a/src/conf/device_conf.c
+++ b/src/conf/device_conf.c
@@ -67,6 +67,11 @@ virDeviceHostdevPCIDriverInfoParseXML(xmlNodePtr node,
return -1;
}
+ if (virXMLPropTristateBool(node, "iommufd",
+ VIR_XML_PROP_NONE,
+ &driver->iommufd) < 0)
+ return -1;
+
driver->model = virXMLPropString(node, "model");
return 0;
}
@@ -93,6 +98,12 @@ virDeviceHostdevPCIDriverInfoFormat(virBuffer *buf,
virBufferEscapeString(&driverAttrBuf, " model='%s'", driver->model);
+ if (driver->iommufd == VIR_TRISTATE_BOOL_YES) {
+ virBufferAddLit(&driverAttrBuf, " iommufd='yes'");
+ } else if (driver->iommufd == VIR_TRISTATE_BOOL_NO) {
+ virBufferAddLit(&driverAttrBuf, " iommufd='no'");
+ }
+
virXMLFormatElement(buf, "driver", &driverAttrBuf, NULL);
return 0;
}
diff --git a/src/conf/device_conf.h b/src/conf/device_conf.h
index e570f51824..116b959143 100644
--- a/src/conf/device_conf.h
+++ b/src/conf/device_conf.h
@@ -47,6 +47,7 @@ VIR_ENUM_DECL(virDeviceHostdevPCIDriverName);
struct _virDeviceHostdevPCIDriverInfo {
virDeviceHostdevPCIDriverName name;
char *model;
+ virTristateBool iommufd;
};
typedef enum {
diff --git a/src/conf/schemas/basictypes.rng b/src/conf/schemas/basictypes.rng
index 5689170fad..381e0ac24f 100644
--- a/src/conf/schemas/basictypes.rng
+++ b/src/conf/schemas/basictypes.rng
@@ -673,6 +673,11 @@
<ref name="genericName"/>
</attribute>
</optional>
+ <optional>
+ <attribute name="iommufd">
+ <ref name="virYesNo"/>
+ </attribute>
+ </optional>
<empty/>
</element>
</define>
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index fb89dbec27..1fb31d1721 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -4754,6 +4754,7 @@ qemuBuildPCIHostdevDevProps(const virDomainDef *def,
g_autofree char *host = virPCIDeviceAddressAsString(&pcisrc->addr);
const char *failover_pair_id = NULL;
const char *driver = NULL;
+ const char *iommufdId = NULL;
/* 'ramfb' property must be omitted unless it's to be enabled */
bool ramfb = pcisrc->ramfb == VIR_TRISTATE_SWITCH_ON;
@@ -4787,6 +4788,9 @@ qemuBuildPCIHostdevDevProps(const virDomainDef *def,
teaming->persistent)
failover_pair_id = teaming->persistent;
+ if (pcisrc->driver.iommufd == VIR_TRISTATE_BOOL_YES)
+ iommufdId = "iommufd0";
+
if (virJSONValueObjectAdd(&props,
"s:driver", driver,
"s:host", host,
@@ -4795,6 +4799,7 @@ qemuBuildPCIHostdevDevProps(const virDomainDef *def,
"S:failover_pair_id", failover_pair_id,
"S:display", qemuOnOffAuto(pcisrc->display),
"B:ramfb", ramfb,
+ "S:iommufd", iommufdId,
NULL) < 0)
return NULL;
@@ -5314,6 +5319,44 @@ qemuBuildHostdevCommandLine(virCommand *cmd,
}
+static int
+qemuBuildIOMMUFDCommandLine(virCommand *cmd,
+ const virDomainDef *def)
+{
+ size_t i;
+
+ for (i = 0; i < def->nhostdevs; i++) {
+ virDomainHostdevDef *hostdev = def->hostdevs[i];
+ virDomainHostdevSubsys *subsys = &hostdev->source.subsys;
+ g_autoptr(virJSONValue) props = NULL;
+
+ if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
+ continue;
+
+ if (subsys->type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
+ continue;
+
+ if (hostdev->info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_UNASSIGNED)
+ continue;
+
+ if (subsys->u.pci.driver.iommufd != VIR_TRISTATE_BOOL_YES)
+ continue;
+
+ if (qemuMonitorCreateObjectProps(&props, "iommufd",
+ "iommufd0",
+ NULL) < 0)
+ return -1;
+
+ if (qemuBuildObjectCommandlineFromJSON(cmd, props) < 0)
+ return -1;
+
+ break;
+ }
+
+ return 0;
+}
+
+
static int
qemuBuildMonitorCommandLine(virCommand *cmd,
qemuDomainObjPrivate *priv)
@@ -10926,6 +10969,9 @@ qemuBuildCommandLine(virDomainObj *vm,
if (qemuBuildRedirdevCommandLine(cmd, def, qemuCaps) < 0)
return NULL;
+ if (qemuBuildIOMMUFDCommandLine(cmd, def) < 0)
+ return NULL;
+
if (qemuBuildHostdevCommandLine(cmd, def, qemuCaps) < 0)
return NULL;
--
2.52.0

View File

@ -0,0 +1,220 @@
From 3f03b1cbc20d0af7900cc43cc576a356a95a292b Mon Sep 17 00:00:00 2001
Message-ID: <3f03b1cbc20d0af7900cc43cc576a356a95a292b.1771336681.git.jdenemar@redhat.com>
From: Peter Krempa <pkrempa@redhat.com>
Date: Thu, 11 Dec 2025 19:47:16 +0100
Subject: [PATCH] qemu: Implement support for persistent reservation migration
control
The 'migration' attribute for the '<reservations>' element allows to
control the persistent reservation migration feature independently of
the machine type default.
Add the XML plumbing and qemu support.
We consider it ABI for now since it influences qemu migration protocol.
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit 0d3ef7cb71979172de2c531d865e4525a314f902)
https://issues.redhat.com/browse/RHEL-140614 [rhel-9.8]
https://issues.redhat.com/browse/RHEL-135115 [rhel-10.2]
---
docs/formatdomain.rst | 3 +++
src/conf/domain_conf.c | 21 +++++++++++++++++++
src/conf/schemas/storagecommon.rng | 5 +++++
src/conf/storage_source_conf.c | 10 +++++++++
src/conf/storage_source_conf.h | 2 ++
src/qemu/qemu_command.c | 4 ++++
src/qemu/qemu_validate.c | 16 ++++++++++++++
...irtio-scsi-reservations.x86_64-latest.args | 2 +-
.../disk-virtio-scsi-reservations.xml | 2 +-
9 files changed, 63 insertions(+), 2 deletions(-)
diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst
index 167912348e..9836837441 100644
--- a/docs/formatdomain.rst
+++ b/docs/formatdomain.rst
@@ -3169,6 +3169,9 @@ paravirtualized driver is specified via the ``disk`` element.
the socket, and finally ``mode`` which accepts one value ``client``
specifying the role of hypervisor. It's recommended to allow libvirt
manage the persistent reservations.
+ :since:`Since 12.1.0` the ``migration`` (values ``yes``, ``no``) controls
+ whether the hypervisor should attempt to migrate persistent reservations
+ during migration.
``initiator``
:since:`Since 4.7.0`, the ``initiator`` element is supported for
a disk ``type`` "network" that is using a ``source`` element with the
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 902c1188ef..f5c4d135a9 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -20951,6 +20951,27 @@ virDomainDiskDefCheckABIStability(virDomainDiskDef *src,
return false;
}
+ /* While not guest visible it influences the qemu migration stream so
+ * we need to keep it identical */
+ if (src->src->pr || dst->src->pr) {
+ virTristateBool srcmig = VIR_TRISTATE_BOOL_ABSENT;
+ virTristateBool dstmig = VIR_TRISTATE_BOOL_ABSENT;
+
+ if (src->src->pr)
+ srcmig = src->src->pr->migration;
+
+ if (dst->src->pr)
+ dstmig = dst->src->pr->migration;
+
+ if (srcmig != dstmig) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("Target disk reservations 'migration' property %1$s does not match source %2$s"),
+ virTristateBoolTypeToString(dstmig),
+ virTristateBoolTypeToString(srcmig));
+ return false;
+ }
+ }
+
if (!virDomainVirtioOptionsCheckABIStability(src->virtio, dst->virtio))
return false;
diff --git a/src/conf/schemas/storagecommon.rng b/src/conf/schemas/storagecommon.rng
index 14704c737e..450d53131f 100644
--- a/src/conf/schemas/storagecommon.rng
+++ b/src/conf/schemas/storagecommon.rng
@@ -104,6 +104,11 @@
<ref name="virYesNo"/>
</attribute>
</optional>
+ <optional>
+ <attribute name="migration">
+ <ref name="virYesNo"/>
+ </attribute>
+ </optional>
<optional>
<ref name="unixSocketSource"/>
</optional>
diff --git a/src/conf/storage_source_conf.c b/src/conf/storage_source_conf.c
index 087de1eaf2..24d4b0de6a 100644
--- a/src/conf/storage_source_conf.c
+++ b/src/conf/storage_source_conf.c
@@ -330,6 +330,11 @@ virStoragePRDefParseXML(xmlXPathContextPtr ctxt)
&prd->managed) < 0)
goto cleanup;
+ if (virXMLPropTristateBool(ctxt->node, "migration",
+ VIR_XML_PROP_NONZERO,
+ &prd->migration) < 0)
+ goto cleanup;
+
type = virXPathString("string(./source[1]/@type)", ctxt);
path = virXPathString("string(./source[1]/@path)", ctxt);
mode = virXPathString("string(./source[1]/@mode)", ctxt);
@@ -384,6 +389,11 @@ virStoragePRDefFormat(virBuffer *buf,
{
virBufferAsprintf(buf, "<reservations managed='%s'",
virTristateBoolTypeToString(prd->managed));
+
+ if (prd->migration != VIR_TRISTATE_BOOL_ABSENT)
+ virBufferAsprintf(buf, " migration='%s'",
+ virTristateBoolTypeToString(prd->migration));
+
if (prd->path &&
(prd->managed == VIR_TRISTATE_BOOL_NO || !migratable)) {
virBufferAddLit(buf, ">\n");
diff --git a/src/conf/storage_source_conf.h b/src/conf/storage_source_conf.h
index fc868b31af..5a4b088eeb 100644
--- a/src/conf/storage_source_conf.h
+++ b/src/conf/storage_source_conf.h
@@ -235,6 +235,8 @@ struct _virStoragePRDef {
virTristateBool managed;
char *path;
+ virTristateBool migration;
+
/* manager object alias */
char *mgralias;
};
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index f355352018..c8626e6d49 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -1691,6 +1691,7 @@ qemuBuildDiskDeviceProps(const virDomainDef *def,
g_autofree char *usbdiskalias = NULL;
const virDomainDeviceInfo *deviceinfo = &disk->info;
g_autoptr(virJSONValue) statistics = NULL;
+ virTristateBool migrate_pr = VIR_TRISTATE_BOOL_ABSENT;
virDomainDeviceInfo usbSCSIinfo = {
.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE,
.addr.drive = { .diskbus = VIR_DOMAIN_DISK_BUS_USB },
@@ -1716,6 +1717,8 @@ qemuBuildDiskDeviceProps(const virDomainDef *def,
case VIR_DOMAIN_DISK_BUS_SCSI:
if (disk->device == VIR_DOMAIN_DISK_DEVICE_LUN) {
driver = "scsi-block";
+ if (disk->src->pr)
+ migrate_pr = disk->src->pr->migration;
} else {
if (disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM) {
driver = "scsi-cd";
@@ -1937,6 +1940,7 @@ qemuBuildDiskDeviceProps(const virDomainDef *def,
"S:rerror", rpolicy,
"A:stats-intervals", &statistics,
"T:dpofua", disk->dpofua, /* SCSI-only, ensured by validation */
+ "T:migrate-pr", migrate_pr, /* 'scsi-block' only, ensured by validation */
NULL) < 0)
return NULL;
diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c
index da08fd17cd..a3dbd9a33b 100644
--- a/src/qemu/qemu_validate.c
+++ b/src/qemu/qemu_validate.c
@@ -3227,6 +3227,22 @@ qemuValidateDomainDeviceDefDiskFrontend(const virDomainDiskDef *disk,
}
}
+ if (disk->src->pr &&
+ disk->src->pr->migration != VIR_TRISTATE_BOOL_ABSENT) {
+ if (disk->device != VIR_DOMAIN_DISK_DEVICE_LUN ||
+ disk->bus != VIR_DOMAIN_DISK_BUS_SCSI) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("persistent reservation migration supported only with 'lun' disks on 'scsi' bus"));
+ return -1;
+ }
+
+ if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_SCSI_BLOCK_MIGRATE_PR)) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("persistent reservation migration not supported by this qemu"));
+ return -1;
+ }
+ }
+
if (disk->rotation_rate) {
if (disk->bus != VIR_DOMAIN_DISK_BUS_SCSI &&
disk->bus != VIR_DOMAIN_DISK_BUS_IDE &&
diff --git a/tests/qemuxmlconfdata/disk-virtio-scsi-reservations.x86_64-latest.args b/tests/qemuxmlconfdata/disk-virtio-scsi-reservations.x86_64-latest.args
index cbc2a0f398..f1d7a450ee 100644
--- a/tests/qemuxmlconfdata/disk-virtio-scsi-reservations.x86_64-latest.args
+++ b/tests/qemuxmlconfdata/disk-virtio-scsi-reservations.x86_64-latest.args
@@ -33,7 +33,7 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.config \
-device '{"driver":"scsi-block","bus":"scsi0.0","channel":0,"scsi-id":0,"lun":0,"drive":"libvirt-2-storage","id":"scsi0-0-0-0","bootindex":1}' \
-object '{"qom-type":"pr-manager-helper","id":"pr-helper-libvirt-1-storage","path":"/path/to/qemu-pr-helper.sock"}' \
-blockdev '{"driver":"host_device","filename":"/dev/HostVG/QEMUGuest2","pr-manager":"pr-helper-libvirt-1-storage","node-name":"libvirt-1-storage","read-only":false}' \
--device '{"driver":"scsi-block","bus":"scsi0.0","channel":0,"scsi-id":0,"lun":1,"drive":"libvirt-1-storage","id":"scsi0-0-0-1"}' \
+-device '{"driver":"scsi-block","bus":"scsi0.0","channel":0,"scsi-id":0,"lun":1,"drive":"libvirt-1-storage","id":"scsi0-0-0-1","migrate-pr":true}' \
-audiodev '{"id":"audio1","driver":"none"}' \
-device '{"driver":"virtio-balloon-pci","id":"balloon0","bus":"pci.0","addr":"0x4"}' \
-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \
diff --git a/tests/qemuxmlconfdata/disk-virtio-scsi-reservations.xml b/tests/qemuxmlconfdata/disk-virtio-scsi-reservations.xml
index 9c55d6ec3e..7f9160ff3a 100644
--- a/tests/qemuxmlconfdata/disk-virtio-scsi-reservations.xml
+++ b/tests/qemuxmlconfdata/disk-virtio-scsi-reservations.xml
@@ -28,7 +28,7 @@
<disk type='block' device='lun'>
<driver name='qemu' type='raw'/>
<source dev='/dev/HostVG/QEMUGuest2'>
- <reservations managed='no'>
+ <reservations managed='no' migration='yes'>
<source type='unix' path='/path/to/qemu-pr-helper.sock' mode='client'/>
</reservations>
</source>
--
2.53.0

View File

@ -0,0 +1,266 @@
From 13871e41d1697608a55fa40d3855193a636109bb Mon Sep 17 00:00:00 2001
Message-ID: <13871e41d1697608a55fa40d3855193a636109bb.1771423658.git.jdenemar@redhat.com>
From: Pavel Hrdina <phrdina@redhat.com>
Date: Mon, 16 Feb 2026 08:59:39 +0100
Subject: [PATCH] qemu: Introduce QEMU_CAPS_OBJECT_IOMMUFD
Detect if QEMU was compiled with IOMMUFD.
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit 4a0ea9bcf13ea05c90f294ba70c767bc79e2ebbe)
Conflicts:
These files don't exist in downstream:
tests/qemucapabilitiesdata/caps_10.1.0_s390x.xml
tests/qemucapabilitiesdata/caps_10.2.0_aarch64.xml
tests/qemucapabilitiesdata/caps_11.0.0_aarch64.xml
tests/qemucapabilitiesdata/caps_11.0.0_x86_64.xml
Resolves: https://issues.redhat.com/browse/RHEL-150351
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
---
src/qemu/qemu_capabilities.c | 4 ++++
src/qemu/qemu_capabilities.h | 3 +++
src/qemu/qemu_validate.c | 8 ++++++++
tests/qemucapabilitiesdata/caps_10.0.0_aarch64.xml | 1 +
tests/qemucapabilitiesdata/caps_10.0.0_s390x.xml | 1 +
tests/qemucapabilitiesdata/caps_10.0.0_x86_64+amdsev.xml | 1 +
tests/qemucapabilitiesdata/caps_10.0.0_x86_64.xml | 1 +
.../qemucapabilitiesdata/caps_10.1.0_x86_64+inteltdx.xml | 1 +
tests/qemucapabilitiesdata/caps_10.1.0_x86_64.xml | 1 +
tests/qemucapabilitiesdata/caps_10.2.0_x86_64+mshv.xml | 1 +
tests/qemucapabilitiesdata/caps_10.2.0_x86_64.xml | 1 +
tests/qemucapabilitiesdata/caps_9.0.0_x86_64.xml | 1 +
tests/qemucapabilitiesdata/caps_9.1.0_s390x.xml | 1 +
tests/qemucapabilitiesdata/caps_9.1.0_x86_64.xml | 1 +
tests/qemucapabilitiesdata/caps_9.2.0_s390x.xml | 1 +
tests/qemucapabilitiesdata/caps_9.2.0_x86_64+amdsev.xml | 1 +
tests/qemucapabilitiesdata/caps_9.2.0_x86_64.xml | 1 +
17 files changed, 29 insertions(+)
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index 2c8bd62c99..c23ff5539a 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -756,6 +756,9 @@ VIR_ENUM_IMPL(virQEMUCaps,
"query-accelerators", /* QEMU_CAPS_QUERY_ACCELERATORS */
"mshv", /* QEMU_CAPS_MSHV */
"scsi-block.migrate-pr", /* QEMU_CAPS_DEVICE_SCSI_BLOCK_MIGRATE_PR */
+
+ /* 490 */
+ "iommufd", /* QEMU_CAPS_OBJECT_IOMMUFD */
);
@@ -1463,6 +1466,7 @@ struct virQEMUCapsStringFlags virQEMUCapsObjectTypes[] = {
{ "tpm-emulator", QEMU_CAPS_DEVICE_TPM_EMULATOR },
{ "tpm-passthrough", QEMU_CAPS_DEVICE_TPM_PASSTHROUGH },
{ "acpi-generic-initiator", QEMU_CAPS_ACPI_GENERIC_INITIATOR },
+ { "iommufd", QEMU_CAPS_OBJECT_IOMMUFD },
};
diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
index 0c76f2edda..f7c8680f94 100644
--- a/src/qemu/qemu_capabilities.h
+++ b/src/qemu/qemu_capabilities.h
@@ -732,6 +732,9 @@ typedef enum { /* virQEMUCapsFlags grouping marker for syntax-check */
QEMU_CAPS_MSHV, /* -accel mshv */
QEMU_CAPS_DEVICE_SCSI_BLOCK_MIGRATE_PR, /* persistent reservation migration support */
+ /* 490 */
+ QEMU_CAPS_OBJECT_IOMMUFD, /* -object iommufd */
+
QEMU_CAPS_LAST /* this must always be the last item */
} virQEMUCapsFlags;
diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c
index a3dbd9a33b..18f148f48c 100644
--- a/src/qemu/qemu_validate.c
+++ b/src/qemu/qemu_validate.c
@@ -2723,6 +2723,14 @@ qemuValidateDomainDeviceDefHostdev(const virDomainHostdevDef *hostdev,
_("VFIO PCI device assignment is not supported by this version of qemu"));
return -1;
}
+
+ if (hostdev->source.subsys.u.pci.driver.iommufd == VIR_TRISTATE_BOOL_YES) {
+ if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_OBJECT_IOMMUFD)) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("IOMMUFD is not supported by this version of qemu"));
+ return -1;
+ }
+ }
}
if (hostdev->writeFiltering != VIR_TRISTATE_BOOL_ABSENT) {
diff --git a/tests/qemucapabilitiesdata/caps_10.0.0_aarch64.xml b/tests/qemucapabilitiesdata/caps_10.0.0_aarch64.xml
index 90e8d868cc..bbb8b33cde 100644
--- a/tests/qemucapabilitiesdata/caps_10.0.0_aarch64.xml
+++ b/tests/qemucapabilitiesdata/caps_10.0.0_aarch64.xml
@@ -163,6 +163,7 @@
<flag name='nvme-ns'/>
<flag name='usb-bot'/>
<flag name='acpi-generic-initiator'/>
+ <flag name='iommufd'/>
<version>10000000</version>
<microcodeVersion>61700285</microcodeVersion>
<package>v10.0.0</package>
diff --git a/tests/qemucapabilitiesdata/caps_10.0.0_s390x.xml b/tests/qemucapabilitiesdata/caps_10.0.0_s390x.xml
index 82a66a6524..cf00ac4ea0 100644
--- a/tests/qemucapabilitiesdata/caps_10.0.0_s390x.xml
+++ b/tests/qemucapabilitiesdata/caps_10.0.0_s390x.xml
@@ -136,6 +136,7 @@
<flag name='nvme'/>
<flag name='nvme-ns'/>
<flag name='usb-bot'/>
+ <flag name='iommufd'/>
<version>10000000</version>
<microcodeVersion>39100285</microcodeVersion>
<package>v10.0.0</package>
diff --git a/tests/qemucapabilitiesdata/caps_10.0.0_x86_64+amdsev.xml b/tests/qemucapabilitiesdata/caps_10.0.0_x86_64+amdsev.xml
index cfce1c963d..5acd1a33fd 100644
--- a/tests/qemucapabilitiesdata/caps_10.0.0_x86_64+amdsev.xml
+++ b/tests/qemucapabilitiesdata/caps_10.0.0_x86_64+amdsev.xml
@@ -209,6 +209,7 @@
<flag name='amd-iommu'/>
<flag name='usb-bot'/>
<flag name='acpi-generic-initiator'/>
+ <flag name='iommufd'/>
<version>10000000</version>
<microcodeVersion>43100285</microcodeVersion>
<package>v10.0.0</package>
diff --git a/tests/qemucapabilitiesdata/caps_10.0.0_x86_64.xml b/tests/qemucapabilitiesdata/caps_10.0.0_x86_64.xml
index f94c8388d6..50f58791e6 100644
--- a/tests/qemucapabilitiesdata/caps_10.0.0_x86_64.xml
+++ b/tests/qemucapabilitiesdata/caps_10.0.0_x86_64.xml
@@ -209,6 +209,7 @@
<flag name='amd-iommu.pci-id'/>
<flag name='usb-bot'/>
<flag name='acpi-generic-initiator'/>
+ <flag name='iommufd'/>
<version>10000000</version>
<microcodeVersion>43100285</microcodeVersion>
<package>v10.0.0</package>
diff --git a/tests/qemucapabilitiesdata/caps_10.1.0_x86_64+inteltdx.xml b/tests/qemucapabilitiesdata/caps_10.1.0_x86_64+inteltdx.xml
index 8e989a139f..e321c352a3 100644
--- a/tests/qemucapabilitiesdata/caps_10.1.0_x86_64+inteltdx.xml
+++ b/tests/qemucapabilitiesdata/caps_10.1.0_x86_64+inteltdx.xml
@@ -191,6 +191,7 @@
<flag name='usb-bot'/>
<flag name='tdx-guest'/>
<flag name='acpi-generic-initiator'/>
+ <flag name='iommufd'/>
<version>10000050</version>
<microcodeVersion>43100286</microcodeVersion>
<package>v10.0.0-1724-gf9a3def17b</package>
diff --git a/tests/qemucapabilitiesdata/caps_10.1.0_x86_64.xml b/tests/qemucapabilitiesdata/caps_10.1.0_x86_64.xml
index 520a3d8ee8..2d52659520 100644
--- a/tests/qemucapabilitiesdata/caps_10.1.0_x86_64.xml
+++ b/tests/qemucapabilitiesdata/caps_10.1.0_x86_64.xml
@@ -214,6 +214,7 @@
<flag name='tdx-guest'/>
<flag name='qom-list-get'/>
<flag name='acpi-generic-initiator'/>
+ <flag name='iommufd'/>
<version>10001000</version>
<microcodeVersion>43100286</microcodeVersion>
<package>v10.1.0</package>
diff --git a/tests/qemucapabilitiesdata/caps_10.2.0_x86_64+mshv.xml b/tests/qemucapabilitiesdata/caps_10.2.0_x86_64+mshv.xml
index 874fd7bddb..eb2ab001a6 100644
--- a/tests/qemucapabilitiesdata/caps_10.2.0_x86_64+mshv.xml
+++ b/tests/qemucapabilitiesdata/caps_10.2.0_x86_64+mshv.xml
@@ -201,6 +201,7 @@
<flag name='acpi-generic-initiator'/>
<flag name='query-accelerators'/>
<flag name='mshv'/>
+ <flag name='iommufd'/>
<version>10001050</version>
<microcodeVersion>43100287</microcodeVersion>
<package>v10.1.0-1778-ge090e0312d</package>
diff --git a/tests/qemucapabilitiesdata/caps_10.2.0_x86_64.xml b/tests/qemucapabilitiesdata/caps_10.2.0_x86_64.xml
index 7d5a75ce88..c4ea924c1f 100644
--- a/tests/qemucapabilitiesdata/caps_10.2.0_x86_64.xml
+++ b/tests/qemucapabilitiesdata/caps_10.2.0_x86_64.xml
@@ -216,6 +216,7 @@
<flag name='disk-timed-stats'/>
<flag name='query-accelerators'/>
<flag name='scsi-block.migrate-pr'/>
+ <flag name='iommufd'/>
<version>10001091</version>
<microcodeVersion>43100287</microcodeVersion>
<package>v10.2.0-rc1-38-gfb241d0a1f</package>
diff --git a/tests/qemucapabilitiesdata/caps_9.0.0_x86_64.xml b/tests/qemucapabilitiesdata/caps_9.0.0_x86_64.xml
index 1f2e27a218..88bd502fee 100644
--- a/tests/qemucapabilitiesdata/caps_9.0.0_x86_64.xml
+++ b/tests/qemucapabilitiesdata/caps_9.0.0_x86_64.xml
@@ -204,6 +204,7 @@
<flag name='amd-iommu'/>
<flag name='usb-bot'/>
<flag name='acpi-generic-initiator'/>
+ <flag name='iommufd'/>
<version>9000000</version>
<microcodeVersion>43100245</microcodeVersion>
<package>v9.0.0</package>
diff --git a/tests/qemucapabilitiesdata/caps_9.1.0_s390x.xml b/tests/qemucapabilitiesdata/caps_9.1.0_s390x.xml
index b961f79808..3d2692b02c 100644
--- a/tests/qemucapabilitiesdata/caps_9.1.0_s390x.xml
+++ b/tests/qemucapabilitiesdata/caps_9.1.0_s390x.xml
@@ -126,6 +126,7 @@
<flag name='nvme'/>
<flag name='nvme-ns'/>
<flag name='usb-bot'/>
+ <flag name='iommufd'/>
<version>9001000</version>
<microcodeVersion>39100246</microcodeVersion>
<package>v9.1.0</package>
diff --git a/tests/qemucapabilitiesdata/caps_9.1.0_x86_64.xml b/tests/qemucapabilitiesdata/caps_9.1.0_x86_64.xml
index 35ddf30736..66578099a7 100644
--- a/tests/qemucapabilitiesdata/caps_9.1.0_x86_64.xml
+++ b/tests/qemucapabilitiesdata/caps_9.1.0_x86_64.xml
@@ -203,6 +203,7 @@
<flag name='amd-iommu'/>
<flag name='usb-bot'/>
<flag name='acpi-generic-initiator'/>
+ <flag name='iommufd'/>
<version>9001000</version>
<microcodeVersion>43100246</microcodeVersion>
<package>v9.1.0</package>
diff --git a/tests/qemucapabilitiesdata/caps_9.2.0_s390x.xml b/tests/qemucapabilitiesdata/caps_9.2.0_s390x.xml
index e9f79261f7..9f95ed891e 100644
--- a/tests/qemucapabilitiesdata/caps_9.2.0_s390x.xml
+++ b/tests/qemucapabilitiesdata/caps_9.2.0_s390x.xml
@@ -129,6 +129,7 @@
<flag name='nvme'/>
<flag name='nvme-ns'/>
<flag name='usb-bot'/>
+ <flag name='iommufd'/>
<version>9002000</version>
<microcodeVersion>39100247</microcodeVersion>
<package>v9.2.0</package>
diff --git a/tests/qemucapabilitiesdata/caps_9.2.0_x86_64+amdsev.xml b/tests/qemucapabilitiesdata/caps_9.2.0_x86_64+amdsev.xml
index 0e52c3e23d..6636346bc5 100644
--- a/tests/qemucapabilitiesdata/caps_9.2.0_x86_64+amdsev.xml
+++ b/tests/qemucapabilitiesdata/caps_9.2.0_x86_64+amdsev.xml
@@ -207,6 +207,7 @@
<flag name='amd-iommu'/>
<flag name='usb-bot'/>
<flag name='acpi-generic-initiator'/>
+ <flag name='iommufd'/>
<version>9002000</version>
<microcodeVersion>43100247</microcodeVersion>
<package>v9.2.0</package>
diff --git a/tests/qemucapabilitiesdata/caps_9.2.0_x86_64.xml b/tests/qemucapabilitiesdata/caps_9.2.0_x86_64.xml
index 95f8a4d878..dee30415aa 100644
--- a/tests/qemucapabilitiesdata/caps_9.2.0_x86_64.xml
+++ b/tests/qemucapabilitiesdata/caps_9.2.0_x86_64.xml
@@ -205,6 +205,7 @@
<flag name='amd-iommu'/>
<flag name='usb-bot'/>
<flag name='acpi-generic-initiator'/>
+ <flag name='iommufd'/>
<version>9002000</version>
<microcodeVersion>43100247</microcodeVersion>
<package>v9.2.0</package>
--
2.53.0

View File

@ -0,0 +1,277 @@
From 94e2bf223d9fb7b9b65deaf8f2fbafb01dff5578 Mon Sep 17 00:00:00 2001
Message-ID: <94e2bf223d9fb7b9b65deaf8f2fbafb01dff5578.1770383182.git.jdenemar@redhat.com>
From: Nathan Chen <nathanc@nvidia.com>
Date: Fri, 30 Jan 2026 10:59:13 -0800
Subject: [PATCH] qemu: Introduce privateData for hostdevs
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Introduce private data for hostdevs and allocate hostdev
private data by default.
Signed-off-by: Ján Tomko <jtomko@redhat.com>
Signed-off-by: Nathan Chen <nathanc@nvidia.com>
Reviewed-by: Pavel Hrdina <phrdina@redhat.com>
(cherry picked from commit 1043e04e17ed4be59b46e925089204333c08f05e)
Resolves: https://issues.redhat.com/browse/RHEL-74202
Resolves: https://issues.redhat.com/browse/RHEL-126346
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
---
src/bhyve/bhyve_parse_command.c | 2 +-
src/conf/domain_conf.c | 13 +++++++++--
src/conf/domain_conf.h | 5 ++++-
src/libxl/xen_common.c | 2 +-
src/libxl/xen_xl.c | 2 +-
src/lxc/lxc_native.c | 2 +-
src/qemu/qemu_domain.c | 40 +++++++++++++++++++++++++++++++++
src/qemu/qemu_domain.h | 15 +++++++++++++
src/vbox/vbox_common.c | 2 +-
tests/virhostdevtest.c | 2 +-
10 files changed, 76 insertions(+), 9 deletions(-)
diff --git a/src/bhyve/bhyve_parse_command.c b/src/bhyve/bhyve_parse_command.c
index d62ea64beb..8b405206bd 100644
--- a/src/bhyve/bhyve_parse_command.c
+++ b/src/bhyve/bhyve_parse_command.c
@@ -687,7 +687,7 @@ bhyveParsePassthru(virDomainDef *def G_GNUC_UNUSED,
return -1;
}
- hostdev = virDomainHostdevDefNew();
+ hostdev = virDomainHostdevDefNew(NULL);
hostdev->mode = VIR_DOMAIN_HOSTDEV_MODE_SUBSYS;
hostdev->source.subsys.type = VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI;
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 541dad5bdc..f950f7c75d 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -2733,6 +2733,8 @@ virDomainHostdevDefClear(virDomainHostdevDef *def)
case VIR_DOMAIN_HOSTDEV_MODE_LAST:
break;
}
+
+ g_clear_pointer(&def->privateData, virObjectUnref);
}
@@ -3483,7 +3485,7 @@ void virDomainVideoDefFree(virDomainVideoDef *def)
virDomainHostdevDef *
-virDomainHostdevDefNew(void)
+virDomainHostdevDefNew(virDomainXMLOption *xmlopt)
{
virDomainHostdevDef *def;
@@ -3491,6 +3493,13 @@ virDomainHostdevDefNew(void)
def->info = g_new0(virDomainDeviceInfo, 1);
+ if (xmlopt && xmlopt->privateData.hostdevNew &&
+ !(def->privateData = xmlopt->privateData.hostdevNew())) {
+ VIR_FREE(def->info);
+ VIR_FREE(def);
+ return NULL;
+ }
+
return def;
}
@@ -13678,7 +13687,7 @@ virDomainHostdevDefParseXML(virDomainXMLOption *xmlopt,
ctxt->node = node;
- def = virDomainHostdevDefNew();
+ def = virDomainHostdevDefNew(xmlopt);
if (virXMLPropEnumDefault(node, "mode", virDomainHostdevModeTypeFromString,
VIR_XML_PROP_NONE,
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index cb35ff06bd..8f53ed96c0 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -364,6 +364,8 @@ struct _virDomainHostdevDef {
*/
virDomainNetDef *parentnet;
+ virObject *privateData;
+
virDomainHostdevMode mode;
virDomainStartupPolicy startupPolicy;
bool managed;
@@ -3588,6 +3590,7 @@ struct _virDomainXMLPrivateDataCallbacks {
virDomainXMLPrivateDataNewFunc vsockNew;
virDomainXMLPrivateDataNewFunc cryptoNew;
virDomainXMLPrivateDataNewFunc graphicsNew;
+ virDomainXMLPrivateDataNewFunc hostdevNew;
virDomainXMLPrivateDataNewFunc networkNew;
virDomainXMLPrivateDataNetParseFunc networkParse;
virDomainXMLPrivateDataNetFormatFunc networkFormat;
@@ -3797,7 +3800,7 @@ virDomainVideoDef *virDomainVideoDefNew(virDomainXMLOption *xmlopt);
void virDomainVideoDefFree(virDomainVideoDef *def);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(virDomainVideoDef, virDomainVideoDefFree);
void virDomainVideoDefClear(virDomainVideoDef *def);
-virDomainHostdevDef *virDomainHostdevDefNew(void);
+virDomainHostdevDef *virDomainHostdevDefNew(virDomainXMLOption *xmlopt);
void virDomainHostdevDefFree(virDomainHostdevDef *def);
void virDomainHubDefFree(virDomainHubDef *def);
void virDomainRedirdevDefFree(virDomainRedirdevDef *def);
diff --git a/src/libxl/xen_common.c b/src/libxl/xen_common.c
index 666c6cae20..f19e4f6abb 100644
--- a/src/libxl/xen_common.c
+++ b/src/libxl/xen_common.c
@@ -445,7 +445,7 @@ xenParsePCI(char *entry)
}
}
- hostdev = virDomainHostdevDefNew();
+ hostdev = virDomainHostdevDefNew(NULL);
hostdev->managed = false;
hostdev->writeFiltering = filtered;
hostdev->source.subsys.type = VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI;
diff --git a/src/libxl/xen_xl.c b/src/libxl/xen_xl.c
index b2ff0edcf2..e62302736b 100644
--- a/src/libxl/xen_xl.c
+++ b/src/libxl/xen_xl.c
@@ -930,7 +930,7 @@ xenParseXLUSB(virConf *conf, virDomainDef *def)
key = nextkey;
}
- hostdev = virDomainHostdevDefNew();
+ hostdev = virDomainHostdevDefNew(NULL);
hostdev->managed = false;
hostdev->source.subsys.type = VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB;
hostdev->source.subsys.u.usb.bus = busNum;
diff --git a/src/lxc/lxc_native.c b/src/lxc/lxc_native.c
index 7700804429..a94427b027 100644
--- a/src/lxc/lxc_native.c
+++ b/src/lxc/lxc_native.c
@@ -376,7 +376,7 @@ lxcCreateNetDef(const char *type,
static virDomainHostdevDef *
lxcCreateHostdevDef(const char *data)
{
- virDomainHostdevDef *hostdev = virDomainHostdevDefNew();
+ virDomainHostdevDef *hostdev = virDomainHostdevDefNew(NULL);
hostdev->mode = VIR_DOMAIN_HOSTDEV_MODE_CAPABILITIES;
hostdev->source.caps.type = VIR_DOMAIN_HOSTDEV_CAPS_TYPE_NET;
hostdev->source.caps.u.net.ifname = g_strdup(data);
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 486a0e7913..3366214677 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -1238,6 +1238,45 @@ qemuDomainNetworkPrivateFormat(const virDomainNetDef *net,
}
+static virClass *qemuDomainHostdevPrivateClass;
+
+static void
+qemuDomainHostdevPrivateDispose(void *obj)
+{
+ qemuDomainHostdevPrivate *priv = obj;
+
+ VIR_FORCE_CLOSE(priv->vfioDeviceFd);
+}
+
+
+static int
+qemuDomainHostdevPrivateOnceInit(void)
+{
+ if (!VIR_CLASS_NEW(qemuDomainHostdevPrivate, virClassForObject()))
+ return -1;
+
+ return 0;
+}
+
+VIR_ONCE_GLOBAL_INIT(qemuDomainHostdevPrivate);
+
+virObject *
+qemuDomainHostdevPrivateNew(void)
+{
+ qemuDomainHostdevPrivate *priv;
+
+ if (qemuDomainHostdevPrivateInitialize() < 0)
+ return NULL;
+
+ if (!(priv = virObjectNew(qemuDomainHostdevPrivateClass)))
+ return NULL;
+
+ priv->vfioDeviceFd = -1;
+
+ return (virObject *) priv;
+}
+
+
/* qemuDomainSecretInfoSetup:
* @priv: pointer to domain private object
* @alias: alias of the secret
@@ -3563,6 +3602,7 @@ virDomainXMLPrivateDataCallbacks virQEMUDriverPrivateDataCallbacks = {
.chrSourceNew = qemuDomainChrSourcePrivateNew,
.vsockNew = qemuDomainVsockPrivateNew,
.graphicsNew = qemuDomainGraphicsPrivateNew,
+ .hostdevNew = qemuDomainHostdevPrivateNew,
.networkNew = qemuDomainNetworkPrivateNew,
.networkParse = qemuDomainNetworkPrivateParse,
.networkFormat = qemuDomainNetworkPrivateFormat,
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
index b9bb338682..88c8416aa4 100644
--- a/src/qemu/qemu_domain.h
+++ b/src/qemu/qemu_domain.h
@@ -461,6 +461,18 @@ struct _qemuDomainTPMPrivate {
};
+#define QEMU_DOMAIN_HOSTDEV_PRIVATE(hostdev) \
+ ((qemuDomainHostdevPrivate *) (hostdev)->privateData)
+
+typedef struct _qemuDomainHostdevPrivate qemuDomainHostdevPrivate;
+struct _qemuDomainHostdevPrivate {
+ virObject parent;
+
+ /* VFIO device file descriptor for iommufd passthrough */
+ int vfioDeviceFd;
+};
+
+
void
qemuDomainNetworkPrivateClearFDs(qemuDomainNetworkPrivate *priv);
@@ -1175,3 +1187,6 @@ qemuDomainCheckCPU(virArch arch,
bool
qemuDomainMachineSupportsFloppy(const char *machine,
virQEMUCaps *qemuCaps);
+
+virObject *
+qemuDomainHostdevPrivateNew(void);
diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c
index 26c5fdfef6..d2a8cf8da4 100644
--- a/src/vbox/vbox_common.c
+++ b/src/vbox/vbox_common.c
@@ -3090,7 +3090,7 @@ vboxHostDeviceGetXMLDesc(struct _vboxDriver *data, virDomainDef *def, IMachine *
def->hostdevs = g_new0(virDomainHostdevDef *, def->nhostdevs);
for (i = 0; i < def->nhostdevs; i++)
- def->hostdevs[i] = virDomainHostdevDefNew();
+ def->hostdevs[i] = virDomainHostdevDefNew(NULL);
for (i = 0; i < deviceFilters.count; i++) {
PRBool active = PR_FALSE;
diff --git a/tests/virhostdevtest.c b/tests/virhostdevtest.c
index aec474a148..a35c1d9402 100644
--- a/tests/virhostdevtest.c
+++ b/tests/virhostdevtest.c
@@ -124,7 +124,7 @@ myInit(void)
for (i = 0; i < nhostdevs; i++) {
virDomainHostdevSubsys *subsys;
- hostdevs[i] = virDomainHostdevDefNew();
+ hostdevs[i] = virDomainHostdevDefNew(NULL);
if (!hostdevs[i])
goto cleanup;
hostdevs[i]->mode = VIR_DOMAIN_HOSTDEV_MODE_SUBSYS;
--
2.52.0

View File

@ -0,0 +1,123 @@
From 11e31d9728c42cbb9f4a3a564e9ddec5d09849ba Mon Sep 17 00:00:00 2001
Message-ID: <11e31d9728c42cbb9f4a3a564e9ddec5d09849ba.1772815314.git.jdenemar@redhat.com>
From: Andrea Bolognani <abologna@redhat.com>
Date: Tue, 3 Feb 2026 20:26:59 +0100
Subject: [PATCH] qemu: Introduce qemuPrepareNVRAMFileCommon()
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Most of the code in the qemuPrepareNVRAMFile() function can
be reused to create a varstore file from template. Move the
common parts to a generic helper, leaving only the parts
that are NVRAM-specific in the original function.
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
(cherry picked from commit 41fe1199bbad4ab9cc4bda078571cd7bc5897d44)
https://issues.redhat.com/browse/RHEL-82645
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
---
src/qemu/qemu_process.c | 56 +++++++++++++++++++++++++++--------------
1 file changed, 37 insertions(+), 19 deletions(-)
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 1aff3a277b..47deb9abb9 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -4921,45 +4921,40 @@ qemuPrepareNVRAMBlock(virDomainLoaderDef *loader,
static int
-qemuPrepareNVRAMFile(virQEMUDriver *driver,
- virDomainLoaderDef *loader,
- bool reset_nvram)
+qemuPrepareNVRAMFileCommon(virQEMUDriver *driver,
+ const char *path,
+ const char *template,
+ bool reset_nvram)
{
g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
VIR_AUTOCLOSE srcFD = -1;
struct qemuPrepareNVRAMHelperData data;
- if (virFileExists(loader->nvram->path) && !reset_nvram)
+ if (!path)
return 0;
- if (!loader->nvramTemplate) {
+ if (virFileExists(path) && !reset_nvram)
+ return 0;
+
+ if (!template) {
virReportError(VIR_ERR_OPERATION_FAILED,
_("unable to find any master var store for loader: %1$s"),
- loader->path);
+ path);
return -1;
}
- /* If 'nvramTemplateFormat' is empty it means that it's a user-provided
- * template which we couldn't verify. Assume the user knows what they're doing */
- if (loader->nvramTemplateFormat != VIR_STORAGE_FILE_NONE &&
- loader->nvram->format != loader->nvramTemplateFormat) {
- virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
- _("conversion of the nvram template to another target format is not supported"));
- return -1;
- }
-
- if ((srcFD = virFileOpenAs(loader->nvramTemplate, O_RDONLY,
+ if ((srcFD = virFileOpenAs(template, O_RDONLY,
0, -1, -1, 0)) < 0) {
virReportSystemError(-srcFD,
_("Failed to open file '%1$s'"),
- loader->nvramTemplate);
+ template);
return -1;
}
data.srcFD = srcFD;
- data.srcPath = loader->nvramTemplate;
+ data.srcPath = template;
- if (virFileRewrite(loader->nvram->path,
+ if (virFileRewrite(path,
S_IRUSR | S_IWUSR,
cfg->user, cfg->group,
qemuPrepareNVRAMHelper,
@@ -4971,6 +4966,29 @@ qemuPrepareNVRAMFile(virQEMUDriver *driver,
}
+static int
+qemuPrepareNVRAMFile(virQEMUDriver *driver,
+ virDomainLoaderDef *loader,
+ bool reset_nvram)
+{
+ /* If 'nvramTemplateFormat' is empty it means that it's a user-provided
+ * template which we couldn't verify. Assume the user knows what they're doing */
+ if (loader && loader->nvram &&
+ loader->nvramTemplateFormat != VIR_STORAGE_FILE_NONE &&
+ loader->nvram->format != loader->nvramTemplateFormat) {
+ virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
+ _("conversion of the nvram template to another target format is not supported"));
+ return -1;
+ }
+
+ if (qemuPrepareNVRAMFileCommon(driver, loader->nvram->path,
+ loader->nvramTemplate, reset_nvram) < 0)
+ return -1;
+
+ return 0;
+}
+
+
int
qemuPrepareNVRAM(virQEMUDriver *driver,
virDomainDef *def,
--
2.53.0

View File

@ -0,0 +1,135 @@
From b59cc7646f454eb6626e976f20649d2bce3f21e6 Mon Sep 17 00:00:00 2001
Message-ID: <b59cc7646f454eb6626e976f20649d2bce3f21e6.1772815313.git.jdenemar@redhat.com>
From: Andrea Bolognani <abologna@redhat.com>
Date: Wed, 4 Feb 2026 17:43:36 +0100
Subject: [PATCH] qemu: Introduce varstoreDir
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This is the same as the existing nvramDir, except it will be
used to store the files used with the uefi-vars QEMU device.
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
(cherry picked from commit df3121d21ef257c601c0f15deb78deadcc6bffad)
https://issues.redhat.com/browse/RHEL-82645
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
---
libvirt.spec.in | 1 +
src/qemu/meson.build | 1 +
src/qemu/qemu_conf.c | 4 ++++
src/qemu/qemu_conf.h | 1 +
src/qemu/qemu_driver.c | 12 ++++++++++++
tests/testutilsqemu.c | 2 ++
6 files changed, 21 insertions(+)
diff --git a/src/qemu/meson.build b/src/qemu/meson.build
index ff9a904277..b4fb62f14f 100644
--- a/src/qemu/meson.build
+++ b/src/qemu/meson.build
@@ -223,6 +223,7 @@ if conf.has('WITH_QEMU')
localstatedir / 'lib' / 'libvirt' / 'qemu' / 'ram',
localstatedir / 'lib' / 'libvirt' / 'qemu' / 'save',
localstatedir / 'lib' / 'libvirt' / 'qemu' / 'snapshot',
+ localstatedir / 'lib' / 'libvirt' / 'qemu' / 'varstore',
localstatedir / 'lib' / 'libvirt' / 'swtpm',
localstatedir / 'log' / 'libvirt' / 'qemu',
localstatedir / 'log' / 'swtpm' / 'libvirt' / 'qemu',
diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
index 242955200a..0a2eae3d76 100644
--- a/src/qemu/qemu_conf.c
+++ b/src/qemu/qemu_conf.c
@@ -167,6 +167,7 @@ virQEMUDriverConfig *virQEMUDriverConfigNew(bool privileged,
cfg->checkpointDir = g_strdup_printf("%s/checkpoint", cfg->libDir);
cfg->autoDumpPath = g_strdup_printf("%s/dump", cfg->libDir);
cfg->nvramDir = g_strdup_printf("%s/nvram", cfg->libDir);
+ cfg->varstoreDir = g_strdup_printf("%s/varstore", cfg->libDir);
cfg->memoryBackingDir = g_strdup_printf("%s/ram", cfg->libDir);
} else if (privileged) {
cfg->logDir = g_strdup_printf("%s/log/libvirt/qemu", LOCALSTATEDIR);
@@ -188,6 +189,7 @@ virQEMUDriverConfig *virQEMUDriverConfigNew(bool privileged,
cfg->checkpointDir = g_strdup_printf("%s/checkpoint", cfg->libDir);
cfg->autoDumpPath = g_strdup_printf("%s/dump", cfg->libDir);
cfg->nvramDir = g_strdup_printf("%s/nvram", cfg->libDir);
+ cfg->varstoreDir = g_strdup_printf("%s/varstore", cfg->libDir);
cfg->memoryBackingDir = g_strdup_printf("%s/ram", cfg->libDir);
cfg->swtpmStorageDir = g_strdup_printf("%s/lib/libvirt/swtpm",
LOCALSTATEDIR);
@@ -215,6 +217,7 @@ virQEMUDriverConfig *virQEMUDriverConfigNew(bool privileged,
cfg->configBaseDir);
cfg->autoDumpPath = g_strdup_printf("%s/qemu/dump", cfg->configBaseDir);
cfg->nvramDir = g_strdup_printf("%s/qemu/nvram", cfg->configBaseDir);
+ cfg->varstoreDir = g_strdup_printf("%s/qemu/varstore", cfg->configBaseDir);
cfg->memoryBackingDir = g_strdup_printf("%s/qemu/ram", cfg->configBaseDir);
cfg->swtpmStorageDir = g_strdup_printf("%s/qemu/swtpm",
cfg->configBaseDir);
@@ -367,6 +370,7 @@ static void virQEMUDriverConfigDispose(void *obj)
g_free(cfg->checkpointDir);
g_free(cfg->channelTargetDir);
g_free(cfg->nvramDir);
+ g_free(cfg->varstoreDir);
g_free(cfg->defaultTLSx509certdir);
g_free(cfg->defaultTLSx509secretUUID);
diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h
index edb65c99f4..3b97d24622 100644
--- a/src/qemu/qemu_conf.h
+++ b/src/qemu/qemu_conf.h
@@ -120,6 +120,7 @@ struct _virQEMUDriverConfig {
char *checkpointDir;
char *channelTargetDir;
char *nvramDir;
+ char *varstoreDir;
char *swtpmStorageDir;
char *defaultTLSx509certdir;
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index f3e7410f9e..d314aa94ce 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -626,6 +626,11 @@ qemuStateInitialize(bool privileged,
cfg->nvramDir);
goto error;
}
+ if (g_mkdir_with_parents(cfg->varstoreDir, 0777) < 0) {
+ virReportSystemError(errno, _("Failed to create varstore dir %1$s"),
+ cfg->varstoreDir);
+ goto error;
+ }
if (g_mkdir_with_parents(cfg->memoryBackingDir, 0777) < 0) {
virReportSystemError(errno, _("Failed to create memory backing dir %1$s"),
cfg->memoryBackingDir);
@@ -784,6 +789,13 @@ qemuStateInitialize(bool privileged,
(int)cfg->group);
goto error;
}
+ if (chown(cfg->varstoreDir, cfg->user, cfg->group) < 0) {
+ virReportSystemError(errno,
+ _("unable to set ownership of '%1$s' to %2$d:%3$d"),
+ cfg->varstoreDir, (int)cfg->user,
+ (int)cfg->group);
+ goto error;
+ }
if (chown(cfg->memoryBackingDir, cfg->user, cfg->group) < 0) {
virReportSystemError(errno,
_("unable to set ownership of '%1$s' to %2$d:%3$d"),
diff --git a/tests/testutilsqemu.c b/tests/testutilsqemu.c
index 78ec521266..21dfd3141d 100644
--- a/tests/testutilsqemu.c
+++ b/tests/testutilsqemu.c
@@ -336,6 +336,8 @@ int qemuTestDriverInit(virQEMUDriver *driver)
cfg->memoryBackingDir = g_strdup("/var/lib/libvirt/qemu/ram");
VIR_FREE(cfg->nvramDir);
cfg->nvramDir = g_strdup("/var/lib/libvirt/qemu/nvram");
+ VIR_FREE(cfg->varstoreDir);
+ cfg->varstoreDir = g_strdup("/var/lib/libvirt/qemu/varstore");
VIR_FREE(cfg->passtStateDir);
cfg->passtStateDir = g_strdup("/var/run/libvirt/qemu/passt");
VIR_FREE(cfg->dbusStateDir);
--
2.53.0

View File

@ -0,0 +1,111 @@
From cd9099d42dfaa10d7863f1615a35c48db9924191 Mon Sep 17 00:00:00 2001
Message-ID: <cd9099d42dfaa10d7863f1615a35c48db9924191.1771423658.git.jdenemar@redhat.com>
From: Pavel Hrdina <phrdina@redhat.com>
Date: Mon, 16 Feb 2026 09:12:02 +0100
Subject: [PATCH] qemu: Move IOMMUFD validation to qemu_validate
Fail early if kernel doesn't support IOMMUFD.
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit 0c1af67be554d4daa2facfb647ce6e9914da2f06)
Resolves: https://issues.redhat.com/browse/RHEL-150351
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
---
src/libvirt_private.syms | 1 +
src/qemu/qemu_process.c | 8 +-------
src/qemu/qemu_validate.c | 7 +++++++
src/util/viriommufd.c | 13 +++++++++++++
src/util/viriommufd.h | 2 ++
5 files changed, 24 insertions(+), 7 deletions(-)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index e2a7a16347..0904265459 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -2654,6 +2654,7 @@ virInitctlSetRunLevel;
# util/viriommufd.h
virIOMMUFDSetRLimitMode;
+virIOMMUFDSupported;
# util/viriscsi.h
virISCSIConnectionLogin;
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 37e688018c..479437fb34 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -7690,13 +7690,7 @@ qemuProcessOpenIommuFd(virDomainObj *vm)
VIR_DEBUG("Opening IOMMU FD for domain %s", vm->def->name);
if ((fd = open(VIR_IOMMU_DEV_PATH, O_RDWR | O_CLOEXEC)) < 0) {
- if (errno == ENOENT) {
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
- _("IOMMU FD support requires /dev/iommu device"));
- } else {
- virReportSystemError(errno, "%s",
- _("cannot open /dev/iommu"));
- }
+ virReportSystemError(errno, "%s", _("cannot open /dev/iommu"));
return -1;
}
diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c
index 18f148f48c..aa441188cb 100644
--- a/src/qemu/qemu_validate.c
+++ b/src/qemu/qemu_validate.c
@@ -27,6 +27,7 @@
#include "qemu_process.h"
#include "domain_conf.h"
#include "virbitmap.h"
+#include "viriommufd.h"
#include "virlog.h"
#include "virutil.h"
@@ -2730,6 +2731,12 @@ qemuValidateDomainDeviceDefHostdev(const virDomainHostdevDef *hostdev,
_("IOMMUFD is not supported by this version of qemu"));
return -1;
}
+
+ if (!virIOMMUFDSupported()) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("IOMMUFD is not supported by host kernel"));
+ return -1;
+ }
}
}
diff --git a/src/util/viriommufd.c b/src/util/viriommufd.c
index 5af097683d..44b30029a5 100644
--- a/src/util/viriommufd.c
+++ b/src/util/viriommufd.c
@@ -88,3 +88,16 @@ int virIOMMUFDSetRLimitMode(int fd G_GNUC_UNUSED,
}
#endif
+
+/**
+ * virIOMMUFDSupported:
+ *
+ * Check the presence of IOMMU device.
+ *
+ * Retruns: true if it exists, false otherwise
+ */
+bool
+virIOMMUFDSupported(void)
+{
+ return virFileExists(VIR_IOMMU_DEV_PATH);
+}
diff --git a/src/util/viriommufd.h b/src/util/viriommufd.h
index ebecfe3633..ec6be9fa66 100644
--- a/src/util/viriommufd.h
+++ b/src/util/viriommufd.h
@@ -23,3 +23,5 @@
#define VIR_IOMMU_DEV_PATH "/dev/iommu"
int virIOMMUFDSetRLimitMode(int fd, bool processAccounting);
+
+bool virIOMMUFDSupported(void);
--
2.53.0

View File

@ -0,0 +1,79 @@
From 66f478cd56f2f8fbd3bca3b229a8fcafe29bbee0 Mon Sep 17 00:00:00 2001
Message-ID: <66f478cd56f2f8fbd3bca3b229a8fcafe29bbee0.1771423659.git.jdenemar@redhat.com>
From: Pavel Hrdina <phrdina@redhat.com>
Date: Sat, 14 Feb 2026 17:54:57 +0100
Subject: [PATCH] qemu: Save IOMMUFD state into status XML
We need to track if iommufd object was added to the VM when we add
hotplug support.
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit b21b6dcc72f1853f103f3cfbe1ebbcfbf128b458)
Resolves: https://issues.redhat.com/browse/RHEL-150351
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
---
src/qemu/qemu_command.c | 2 ++
src/qemu/qemu_domain.c | 6 ++++++
src/qemu/qemu_domain.h | 1 +
3 files changed, 9 insertions(+)
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index d11d16e533..cca5fed285 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -5359,6 +5359,8 @@ qemuBuildIOMMUFDCommandLine(virCommand *cmd,
if (qemuBuildObjectCommandlineFromJSON(cmd, props) < 0)
return -1;
+ priv->iommufdState = true;
+
return 0;
}
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index ada9d3431c..ccbfc8bac7 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -1976,6 +1976,7 @@ qemuDomainObjPrivateDataClear(qemuDomainObjPrivate *priv)
priv->migrationRecoverSetup = false;
g_clear_pointer(&priv->iommufd, qemuFDPassDirectFree);
+ priv->iommufdState = false;
g_clear_pointer(&priv->memoryBackingDir, g_free);
}
@@ -2844,6 +2845,9 @@ qemuDomainObjPrivateXMLFormat(virBuffer *buf,
priv->preMigrationMemlock);
}
+ if (priv->iommufdState)
+ virBufferAddLit(buf, "<iommufd/>\n");
+
return 0;
}
@@ -3582,6 +3586,8 @@ qemuDomainObjPrivateXMLParse(xmlXPathContextPtr ctxt,
return -1;
}
+ priv->iommufdState = virXPathBoolean("boolean(./iommufd)", ctxt) == 1;
+
return 0;
}
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
index 8aa94fc25b..62c5252b9f 100644
--- a/src/qemu/qemu_domain.h
+++ b/src/qemu/qemu_domain.h
@@ -265,6 +265,7 @@ struct _qemuDomainObjPrivate {
GHashTable *fds;
qemuFDPassDirect *iommufd;
+ bool iommufdState; /* true if --object iommufd was added */
char *memoryBackingDir;
};
--
2.53.0

View File

@ -0,0 +1,132 @@
From f496b6095bf96eb8931b78054a272a5aaf70a2d9 Mon Sep 17 00:00:00 2001
Message-ID: <f496b6095bf96eb8931b78054a272a5aaf70a2d9.1771336682.git.jdenemar@redhat.com>
From: Peter Krempa <pkrempa@redhat.com>
Date: Fri, 23 Jan 2026 17:18:14 +0100
Subject: [PATCH] qemu: Setup disk latency histograms on startup/hotplug/update
Setup the histograms on startup and hotplug of devices via
'qemuProcessSetupDiskPropsRuntime' and facilitate update/reset/disable
of histogram collection via 'qemuDomainChangeDiskLive'.
The latter allows to use the update device API to either clear the bins
or select new bin configuration or disable the histogram altogether
without the need for a specific API.
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit 5787326541be4eafaa7ae3b4f866b3da793d44fe)
https://issues.redhat.com/browse/RHEL-147866 [rhel-9.8]
https://issues.redhat.com/browse/RHEL-131335 [rhel-10.2]
---
src/qemu/qemu_domain.c | 17 +++++++++++++++++
src/qemu/qemu_domain.h | 3 +++
src/qemu/qemu_hotplug.c | 29 +++++++++++++++++++++++++++++
src/qemu/qemu_process.c | 10 ++++++++++
4 files changed, 59 insertions(+)
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 8e1ebe7799..bdab117e96 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -10463,6 +10463,23 @@ qemuDomainInitializePflashStorageSource(virDomainObj *vm,
}
+/**
+ * qemuDomainDiskHasLatencyHistogram:
+ * @disk: disk definition
+ *
+ * Returns whether @disk has any latency histogram settings configured.
+ */
+bool
+qemuDomainDiskHasLatencyHistogram(virDomainDiskDef *disk)
+{
+ return disk->histogram_boundaries ||
+ disk->histogram_boundaries_read ||
+ disk->histogram_boundaries_write ||
+ disk->histogram_boundaries_zone ||
+ disk->histogram_boundaries_flush;
+}
+
+
/**
* qemuDomainDiskBlockJobIsSupported:
*
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
index 3361e97315..30ca67bf76 100644
--- a/src/qemu/qemu_domain.h
+++ b/src/qemu/qemu_domain.h
@@ -1078,6 +1078,9 @@ int
qemuDomainInitializePflashStorageSource(virDomainObj *vm,
virQEMUDriverConfig *cfg);
+bool
+qemuDomainDiskHasLatencyHistogram(virDomainDiskDef *disk);
+
bool
qemuDomainDiskBlockJobIsSupported(virDomainDiskDef *disk);
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index f2dc4469a3..9445599d2c 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -7310,6 +7310,35 @@ qemuDomainChangeDiskLive(virDomainObj *vm,
dev->data.disk->src = NULL;
}
+ if (qemuDomainDiskHasLatencyHistogram(disk) ||
+ qemuDomainDiskHasLatencyHistogram(orig_disk)) {
+ int rc;
+
+ qemuDomainObjEnterMonitor(vm);
+ rc = qemuMonitorBlockLatencyHistogramSet(qemuDomainGetMonitor(vm),
+ QEMU_DOMAIN_DISK_PRIVATE(orig_disk)->qomName,
+ disk->histogram_boundaries,
+ disk->histogram_boundaries_read,
+ disk->histogram_boundaries_write,
+ disk->histogram_boundaries_zone,
+ disk->histogram_boundaries_flush);
+ qemuDomainObjExitMonitor(vm);
+
+ if (rc < 0)
+ return -1;
+
+ g_clear_pointer(&orig_disk->histogram_boundaries, g_free);
+ g_clear_pointer(&orig_disk->histogram_boundaries_read, g_free);
+ g_clear_pointer(&orig_disk->histogram_boundaries_write, g_free);
+ g_clear_pointer(&orig_disk->histogram_boundaries_zone, g_free);
+ g_clear_pointer(&orig_disk->histogram_boundaries_flush, g_free);
+ orig_disk->histogram_boundaries = g_steal_pointer(&disk->histogram_boundaries);
+ orig_disk->histogram_boundaries_read = g_steal_pointer(&disk->histogram_boundaries_read);
+ orig_disk->histogram_boundaries_write = g_steal_pointer(&disk->histogram_boundaries_write);
+ orig_disk->histogram_boundaries_zone = g_steal_pointer(&disk->histogram_boundaries_zone);
+ orig_disk->histogram_boundaries_flush = g_steal_pointer(&disk->histogram_boundaries_flush);
+ }
+
/* in case when we aren't updating disk source we update startup policy here */
orig_disk->startupPolicy = dev->data.disk->startupPolicy;
orig_disk->snapshot = dev->data.disk->snapshot;
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index aadfaa92b0..37e688018c 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -7959,6 +7959,16 @@ qemuProcessSetupDiskPropsRuntime(qemuMonitor *mon,
&disk->blkdeviotune) < 0)
return -1;
+ if (qemuDomainDiskHasLatencyHistogram(disk) &&
+ qemuMonitorBlockLatencyHistogramSet(mon,
+ QEMU_DOMAIN_DISK_PRIVATE(disk)->qomName,
+ disk->histogram_boundaries,
+ disk->histogram_boundaries_read,
+ disk->histogram_boundaries_write,
+ disk->histogram_boundaries_zone,
+ disk->histogram_boundaries_flush) < 0)
+ return -1;
+
return 0;
}
--
2.53.0

View File

@ -0,0 +1,212 @@
From 9a525305075612f540a1d3b2727ddf8b5320ff01 Mon Sep 17 00:00:00 2001
Message-ID: <9a525305075612f540a1d3b2727ddf8b5320ff01.1770383182.git.jdenemar@redhat.com>
From: Nathan Chen <nathanc@nvidia.com>
Date: Fri, 30 Jan 2026 10:59:14 -0800
Subject: [PATCH] qemu: Support per-process memory accounting for iommufd
Implement the IOMMU_OPTION_RLIMIT_MODE
ioctl to set per-process memory accounting for
iommufd. This prevents ENOMEM errors from the
default per-user memory accounting when multiple
VMs under the libvirt-qemu user have their pinned
memory summed and checked against a per-process
RLIMIT_MEMLOCK limit.
Signed-off-by: Nathan Chen <nathanc@nvidia.com>
Reviewed-by: Pavel Hrdina <phrdina@redhat.com>
(cherry picked from commit f91a07d0c8dd583928974e80bb13b54feb5aa908)
Resolves: https://issues.redhat.com/browse/RHEL-74202
Resolves: https://issues.redhat.com/browse/RHEL-126346
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
---
meson.build | 1 +
po/POTFILES | 1 +
src/libvirt_private.syms | 3 ++
src/util/meson.build | 1 +
src/util/viriommufd.c | 90 ++++++++++++++++++++++++++++++++++++++++
src/util/viriommufd.h | 25 +++++++++++
6 files changed, 121 insertions(+)
create mode 100644 src/util/viriommufd.c
create mode 100644 src/util/viriommufd.h
diff --git a/meson.build b/meson.build
index 6ac9d01952..28745e4e32 100644
--- a/meson.build
+++ b/meson.build
@@ -673,6 +673,7 @@ headers = [
'ifaddrs.h',
'libtasn1.h',
'linux/kvm.h',
+ 'linux/iommufd.h',
'mntent.h',
'net/ethernet.h',
'net/if.h',
diff --git a/po/POTFILES b/po/POTFILES
index f0aad35c8c..c78d2b8000 100644
--- a/po/POTFILES
+++ b/po/POTFILES
@@ -303,6 +303,7 @@ src/util/virhostuptime.c
src/util/viridentity.c
src/util/virinhibitor.c
src/util/virinitctl.c
+src/util/viriommufd.c
src/util/viriscsi.c
src/util/virjson.c
src/util/virlease.c
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 4e57e4a8f6..66261ed6cf 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -2652,6 +2652,9 @@ virInhibitorRelease;
virInitctlFifos;
virInitctlSetRunLevel;
+# util/viriommufd.h
+virIOMMUFDSetRLimitMode;
+
# util/viriscsi.h
virISCSIConnectionLogin;
virISCSIConnectionLogout;
diff --git a/src/util/meson.build b/src/util/meson.build
index 4950a795cc..9fb0aa0fe7 100644
--- a/src/util/meson.build
+++ b/src/util/meson.build
@@ -46,6 +46,7 @@ util_sources = [
'viridentity.c',
'virinhibitor.c',
'virinitctl.c',
+ 'viriommufd.c',
'viriscsi.c',
'virjson.c',
'virkeycode.c',
diff --git a/src/util/viriommufd.c b/src/util/viriommufd.c
new file mode 100644
index 0000000000..5af097683d
--- /dev/null
+++ b/src/util/viriommufd.c
@@ -0,0 +1,90 @@
+#include <config.h>
+
+#include "viriommufd.h"
+#include "virlog.h"
+#include "virerror.h"
+#include "virfile.h"
+
+#define VIR_FROM_THIS VIR_FROM_NONE
+
+VIR_LOG_INIT("util.iommufd");
+
+#ifdef __linux__
+
+# include <sys/ioctl.h>
+# include <linux/types.h>
+
+# ifdef HAVE_LINUX_IOMMUFD_H
+# include <linux/iommufd.h>
+# endif
+
+# ifndef IOMMU_OPTION
+
+enum iommufd_option {
+ IOMMU_OPTION_RLIMIT_MODE = 0,
+ IOMMU_OPTION_HUGE_PAGES = 1,
+};
+
+enum iommufd_option_ops {
+ IOMMU_OPTION_OP_SET = 0,
+ IOMMU_OPTION_OP_GET = 1,
+};
+
+struct iommu_option {
+ __u32 size;
+ __u32 option_id;
+ __u16 op;
+ __u16 __reserved;
+ __u32 object_id;
+ __aligned_u64 val64;
+};
+
+# define IOMMUFD_TYPE (';')
+# define IOMMUFD_CMD_OPTION 0x87
+# define IOMMU_OPTION _IO(IOMMUFD_TYPE, IOMMUFD_CMD_OPTION)
+
+# endif
+
+/**
+ * virIOMMUFDSetRLimitMode:
+ * @fd: iommufd file descriptor
+ * @processAccounting: true for per-process, false for per-user
+ *
+ * Set RLIMIT_MEMLOCK accounting mode for the iommufd.
+ *
+ * Returns: 0 on success, -1 on error
+ */
+int
+virIOMMUFDSetRLimitMode(int fd, bool processAccounting)
+{
+ struct iommu_option option = {
+ .size = sizeof(struct iommu_option),
+ .option_id = IOMMU_OPTION_RLIMIT_MODE,
+ .op = IOMMU_OPTION_OP_SET,
+ .__reserved = 0,
+ .object_id = 0,
+ .val64 = processAccounting ? 1 : 0,
+ };
+
+ if (ioctl(fd, IOMMU_OPTION, &option) < 0) {
+ virReportSystemError(errno, "%s",
+ _("failed to set memory accounting for iommufd"));
+ return -1;
+ }
+
+ VIR_DEBUG("Set iommufd rlimit mode to %s-based accounting",
+ processAccounting ? "process" : "user");
+ return 0;
+}
+
+#else
+
+int virIOMMUFDSetRLimitMode(int fd G_GNUC_UNUSED,
+ bool processAccounting G_GNUC_UNUSED)
+{
+ virReportError(VIR_ERR_NO_SUPPORT, "%s",
+ _("IOMMUFD is not supported on this platform"));
+ return -1;
+}
+
+#endif
diff --git a/src/util/viriommufd.h b/src/util/viriommufd.h
new file mode 100644
index 0000000000..ebecfe3633
--- /dev/null
+++ b/src/util/viriommufd.h
@@ -0,0 +1,25 @@
+/*
+ * viriommufd.h: iommufd helpers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include "internal.h"
+
+#define VIR_IOMMU_DEV_PATH "/dev/iommu"
+
+int virIOMMUFDSetRLimitMode(int fd, bool processAccounting);
--
2.52.0

View File

@ -0,0 +1,336 @@
From 01ce19df7986fe190ce212fa05f2caed799cc50f Mon Sep 17 00:00:00 2001
Message-ID: <01ce19df7986fe190ce212fa05f2caed799cc50f.1770383182.git.jdenemar@redhat.com>
From: Nathan Chen <nathanc@nvidia.com>
Date: Fri, 30 Jan 2026 10:59:17 -0800
Subject: [PATCH] qemu: Update Cgroup, namespace, and seclabel for iommufd
When launching a qemu VM with the iommufd feature enabled for VFIO
hostdevs:
- Do not allow cgroup, namespace, and seclabel access to VFIO
paths (/dev/vfio/vfio and /dev/vfio/<iommugroup>)
- Allow access to iommufd paths (/dev/iommu and
/dev/vfio/devices/vfio*) for AppArmor, SELinux, and DAC
Signed-off-by: Nathan Chen <nathanc@nvidia.com>
Reviewed-by: Pavel Hrdina <phrdina@redhat.com>
(cherry picked from commit 7d2f91f9cb572ab95d0916bdd1a46dd198874529)
Resolves: https://issues.redhat.com/browse/RHEL-74202
Resolves: https://issues.redhat.com/browse/RHEL-126346
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
---
src/qemu/qemu_cgroup.c | 3 ++
src/qemu/qemu_namespace.c | 3 ++
src/security/security_apparmor.c | 28 ++++++++++++------
src/security/security_dac.c | 49 +++++++++++++++++++++++++-------
src/security/security_selinux.c | 47 +++++++++++++++++++++++-------
src/security/virt-aa-helper.c | 32 ++++++++++++++++-----
6 files changed, 127 insertions(+), 35 deletions(-)
diff --git a/src/qemu/qemu_cgroup.c b/src/qemu/qemu_cgroup.c
index 7dadef0739..6148990f19 100644
--- a/src/qemu/qemu_cgroup.c
+++ b/src/qemu/qemu_cgroup.c
@@ -479,6 +479,9 @@ qemuSetupHostdevCgroup(virDomainObj *vm,
g_autofree char *path = NULL;
int perms;
+ if (dev->source.subsys.u.pci.driver.iommufd == VIR_TRISTATE_BOOL_YES)
+ return 0;
+
if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_DEVICES))
return 0;
diff --git a/src/qemu/qemu_namespace.c b/src/qemu/qemu_namespace.c
index c689cc3e40..fb0734193d 100644
--- a/src/qemu/qemu_namespace.c
+++ b/src/qemu/qemu_namespace.c
@@ -345,6 +345,9 @@ qemuDomainSetupHostdev(virDomainObj *vm,
{
g_autofree char *path = NULL;
+ if (hostdev->source.subsys.u.pci.driver.iommufd == VIR_TRISTATE_BOOL_YES)
+ return 0;
+
if (qemuDomainGetHostdevPath(hostdev, &path, NULL) < 0)
return -1;
diff --git a/src/security/security_apparmor.c b/src/security/security_apparmor.c
index 68ac39611f..934acfb461 100644
--- a/src/security/security_apparmor.c
+++ b/src/security/security_apparmor.c
@@ -45,6 +45,7 @@
#include "virstring.h"
#include "virscsi.h"
#include "virmdev.h"
+#include "viriommufd.h"
#define VIR_FROM_THIS VIR_FROM_SECURITY
@@ -841,25 +842,36 @@ AppArmorSetSecurityHostdevLabel(virSecurityManager *mgr,
}
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI: {
- virPCIDevice *pci =
+ g_autoptr(virPCIDevice) pci =
virPCIDeviceNew(&pcisrc->addr);
if (!pci)
goto done;
if (pcisrc->driver.name == VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_VFIO) {
- char *vfioGroupDev = virPCIDeviceGetIOMMUGroupDev(pci);
+ if (dev->source.subsys.u.pci.driver.iommufd != VIR_TRISTATE_BOOL_YES) {
+ char *vfioGroupDev = virPCIDeviceGetIOMMUGroupDev(pci);
- if (!vfioGroupDev) {
- virPCIDeviceFree(pci);
- goto done;
+ if (!vfioGroupDev) {
+ goto done;
+ }
+ ret = AppArmorSetSecurityPCILabel(pci, vfioGroupDev, ptr);
+ VIR_FREE(vfioGroupDev);
+ } else {
+ g_autofree char *vfiofdDev = NULL;
+
+ if (virPCIDeviceGetVfioPath(&dev->source.subsys.u.pci.addr, &vfiofdDev) < 0)
+ goto done;
+
+ ret = AppArmorSetSecurityPCILabel(pci, vfiofdDev, ptr);
+ if (ret < 0)
+ goto done;
+
+ ret = AppArmorSetSecurityPCILabel(pci, VIR_IOMMU_DEV_PATH, ptr);
}
- ret = AppArmorSetSecurityPCILabel(pci, vfioGroupDev, ptr);
- VIR_FREE(vfioGroupDev);
} else {
ret = virPCIDeviceFileIterate(pci, AppArmorSetSecurityPCILabel, ptr);
}
- virPCIDeviceFree(pci);
break;
}
diff --git a/src/security/security_dac.c b/src/security/security_dac.c
index 2f788b872a..d0ed22db2d 100644
--- a/src/security/security_dac.c
+++ b/src/security/security_dac.c
@@ -41,6 +41,7 @@
#include "virscsivhost.h"
#include "virstring.h"
#include "virutil.h"
+#include "viriommufd.h"
#define VIR_FROM_THIS VIR_FROM_SECURITY
@@ -1282,14 +1283,27 @@ virSecurityDACSetHostdevLabel(virSecurityManager *mgr,
return -1;
if (pcisrc->driver.name == VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_VFIO) {
- g_autofree char *vfioGroupDev = virPCIDeviceGetIOMMUGroupDev(pci);
+ if (dev->source.subsys.u.pci.driver.iommufd != VIR_TRISTATE_BOOL_YES) {
+ g_autofree char *vfioGroupDev = virPCIDeviceGetIOMMUGroupDev(pci);
- if (!vfioGroupDev)
- return -1;
+ if (!vfioGroupDev)
+ return -1;
- ret = virSecurityDACSetHostdevLabelHelper(vfioGroupDev,
- false,
- &cbdata);
+ ret = virSecurityDACSetHostdevLabelHelper(vfioGroupDev,
+ false,
+ &cbdata);
+ } else {
+ g_autofree char *vfiofdDev = NULL;
+
+ if (virPCIDeviceGetVfioPath(&dev->source.subsys.u.pci.addr, &vfiofdDev) < 0)
+ return -1;
+
+ ret = virSecurityDACSetHostdevLabelHelper(vfiofdDev, false, &cbdata);
+ if (ret < 0)
+ break;
+
+ ret = virSecurityDACSetHostdevLabelHelper(VIR_IOMMU_DEV_PATH, false, &cbdata);
+ }
} else {
ret = virPCIDeviceFileIterate(pci,
virSecurityDACSetPCILabel,
@@ -1443,13 +1457,28 @@ virSecurityDACRestoreHostdevLabel(virSecurityManager *mgr,
return -1;
if (pcisrc->driver.name == VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_VFIO) {
- g_autofree char *vfioGroupDev = virPCIDeviceGetIOMMUGroupDev(pci);
+ if (dev->source.subsys.u.pci.driver.iommufd != VIR_TRISTATE_BOOL_YES) {
+ g_autofree char *vfioGroupDev = virPCIDeviceGetIOMMUGroupDev(pci);
- if (!vfioGroupDev)
- return -1;
+ if (!vfioGroupDev)
+ return -1;
- ret = virSecurityDACRestoreFileLabelInternal(mgr, NULL,
+ ret = virSecurityDACRestoreFileLabelInternal(mgr, NULL,
vfioGroupDev, false);
+ } else {
+ g_autofree char *vfiofdDev = NULL;
+
+ if (virPCIDeviceGetVfioPath(&dev->source.subsys.u.pci.addr, &vfiofdDev) < 0)
+ return -1;
+
+ ret = virSecurityDACRestoreFileLabelInternal(mgr, NULL,
+ vfiofdDev, false);
+ if (ret < 0)
+ break;
+
+ ret = virSecurityDACRestoreFileLabelInternal(mgr, NULL,
+ VIR_IOMMU_DEV_PATH, false);
+ }
} else {
ret = virPCIDeviceFileIterate(pci, virSecurityDACRestorePCILabel, mgr);
}
diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c
index 2f3cc274a5..834383a7de 100644
--- a/src/security/security_selinux.c
+++ b/src/security/security_selinux.c
@@ -41,6 +41,7 @@
#include "virconf.h"
#include "virtpm.h"
#include "virstring.h"
+#include "viriommufd.h"
#define VIR_FROM_THIS VIR_FROM_SECURITY
@@ -2256,14 +2257,27 @@ virSecuritySELinuxSetHostdevSubsysLabel(virSecurityManager *mgr,
return -1;
if (pcisrc->driver.name == VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_VFIO) {
- g_autofree char *vfioGroupDev = virPCIDeviceGetIOMMUGroupDev(pci);
+ if (dev->source.subsys.u.pci.driver.iommufd != VIR_TRISTATE_BOOL_YES) {
+ g_autofree char *vfioGroupDev = virPCIDeviceGetIOMMUGroupDev(pci);
- if (!vfioGroupDev)
- return -1;
+ if (!vfioGroupDev)
+ return -1;
- ret = virSecuritySELinuxSetHostdevLabelHelper(vfioGroupDev,
- false,
- &data);
+ ret = virSecuritySELinuxSetHostdevLabelHelper(vfioGroupDev,
+ false,
+ &data);
+ } else {
+ g_autofree char *vfiofdDev = NULL;
+
+ if (virPCIDeviceGetVfioPath(&dev->source.subsys.u.pci.addr, &vfiofdDev) < 0)
+ return -1;
+
+ ret = virSecuritySELinuxSetHostdevLabelHelper(vfiofdDev, false, &data);
+ if (ret)
+ break;
+
+ ret = virSecuritySELinuxSetHostdevLabelHelper(VIR_IOMMU_DEV_PATH, false, &data);
+ }
} else {
ret = virPCIDeviceFileIterate(pci, virSecuritySELinuxSetPCILabel, &data);
}
@@ -2491,12 +2505,25 @@ virSecuritySELinuxRestoreHostdevSubsysLabel(virSecurityManager *mgr,
return -1;
if (pcisrc->driver.name == VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_VFIO) {
- g_autofree char *vfioGroupDev = virPCIDeviceGetIOMMUGroupDev(pci);
+ if (dev->source.subsys.u.pci.driver.iommufd != VIR_TRISTATE_BOOL_YES) {
+ g_autofree char *vfioGroupDev = virPCIDeviceGetIOMMUGroupDev(pci);
- if (!vfioGroupDev)
- return -1;
+ if (!vfioGroupDev)
+ return -1;
- ret = virSecuritySELinuxRestoreFileLabel(mgr, vfioGroupDev, false, false);
+ ret = virSecuritySELinuxRestoreFileLabel(mgr, vfioGroupDev, false, false);
+ } else {
+ g_autofree char *vfiofdDev = NULL;
+
+ if (virPCIDeviceGetVfioPath(&dev->source.subsys.u.pci.addr, &vfiofdDev) < 0)
+ return -1;
+
+ ret = virSecuritySELinuxRestoreFileLabel(mgr, vfiofdDev, false, false);
+ if (ret < 0)
+ break;
+
+ ret = virSecuritySELinuxRestoreFileLabel(mgr, VIR_IOMMU_DEV_PATH, false, false);
+ }
} else {
ret = virPCIDeviceFileIterate(pci, virSecuritySELinuxRestorePCILabel, mgr);
}
diff --git a/src/security/virt-aa-helper.c b/src/security/virt-aa-helper.c
index de0a826063..29e844c7ff 100644
--- a/src/security/virt-aa-helper.c
+++ b/src/security/virt-aa-helper.c
@@ -50,6 +50,7 @@
#include "virstring.h"
#include "virgettext.h"
#include "virhostdev.h"
+#include "viriommufd.h"
#define VIR_FROM_THIS VIR_FROM_SECURITY
@@ -1114,8 +1115,9 @@ get_files(vahControl * ctl)
virDeviceHostdevPCIDriverName driverName = dev->source.subsys.u.pci.driver.name;
- if (driverName == VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_VFIO ||
- driverName == VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_DEFAULT) {
+ if ((driverName == VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_VFIO ||
+ driverName == VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_DEFAULT) &&
+ dev->source.subsys.u.pci.driver.iommufd != VIR_TRISTATE_BOOL_YES) {
needsVfio = true;
}
@@ -1385,9 +1387,18 @@ get_files(vahControl * ctl)
}
}
- if (ctl->newfile &&
- vah_add_file(&buf, ctl->newfile, "rwk") != 0) {
- return -1;
+ if (ctl->newfile) {
+ const char *perms = "rwk";
+
+ /* VFIO and iommufd devices need mmap permission */
+ if (STRPREFIX(ctl->newfile, "/dev/vfio/devices/vfio") ||
+ STREQ(ctl->newfile, VIR_IOMMU_DEV_PATH)) {
+ perms = "rwm";
+ }
+
+ if (vah_add_file(&buf, ctl->newfile, perms) != 0) {
+ return -1;
+ }
}
ctl->files = virBufferContentAndReset(&buf);
@@ -1561,8 +1572,15 @@ main(int argc, char **argv)
}
}
if (ctl->append && ctl->newfile) {
- if (vah_add_file(&buf, ctl->newfile, "rwk") != 0)
- goto cleanup;
+ const char *perms = "rwk";
+
+ if (STRPREFIX(ctl->newfile, "/dev/vfio/devices/vfio") ||
+ STREQ(ctl->newfile, VIR_IOMMU_DEV_PATH)) {
+ perms = "rwm";
+ }
+
+ if (vah_add_file(&buf, ctl->newfile, perms) != 0)
+ return -1;
} else {
if (ctl->def->virtType == VIR_DOMAIN_VIRT_QEMU ||
ctl->def->virtType == VIR_DOMAIN_VIRT_KQEMU ||
--
2.52.0

View File

@ -0,0 +1,69 @@
From 933524784d813b24aa0970992b820698f1e03180 Mon Sep 17 00:00:00 2001
Message-ID: <933524784d813b24aa0970992b820698f1e03180.1766070439.git.jdenemar@redhat.com>
From: Nathan Chen via Devel <devel@lists.libvirt.org>
Date: Tue, 2 Dec 2025 11:59:47 -0800
Subject: [PATCH] qemu: Use pci_bus to identify multi-smmuv3 model
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Use presence of non-negative pci_bus to identify multi-smmuv3
IOMMU model, instead of the niommus attribute. This allows for
specifying a single arm-smmuv3 on the qemu command line,
instead of both the virt-machine smmuv3 and arm-smmuv3
being specified at the same time.
Signed-off-by: Nathan Chen <nathanc@nvidia.com>
Fixes: e70c4d54d365 conf: Support multiple device-pluggable smmuv3 IOMMUs
Reviewed-by: Ján Tomko <jtomko@redhat.com>
(cherry picked from commit da4305b7bc8d3bd52c60db1905db88e43ebd9868)
https://issues.redhat.com/browse/RHEL-74200
Signed-off-by: Ján Tomko <jtomko@redhat.com>
---
src/qemu/qemu_command.c | 2 +-
src/qemu/qemu_postparse.c | 2 +-
.../iommu-smmuv3-pci-bus-single.aarch64-latest.args | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index b69fe23236..fb89dbec27 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -7192,7 +7192,7 @@ qemuBuildMachineCommandLine(virCommand *cmd,
if (qemuAppendDomainFeaturesMachineParam(&buf, def, qemuCaps) < 0)
return -1;
- if (def->niommus == 1) {
+ if (def->iommus && def->iommus[0]->pci_bus < 0) {
switch (def->iommus[0]->model) {
case VIR_DOMAIN_IOMMU_MODEL_SMMUV3:
virBufferAddLit(&buf, ",iommu=smmuv3");
diff --git a/src/qemu/qemu_postparse.c b/src/qemu/qemu_postparse.c
index dc5ade829a..840d6a1174 100644
--- a/src/qemu/qemu_postparse.c
+++ b/src/qemu/qemu_postparse.c
@@ -1559,7 +1559,7 @@ qemuDomainDefEnableDefaultFeatures(virDomainDef *def,
* domain already has IOMMU without inremap. This will be fixed in
* qemuDomainIOMMUDefPostParse() but there domain definition can't be
* modified so change it now. */
- if (def->iommus && def->niommus == 1 &&
+ if (def->iommus && def->iommus[0]->pci_bus < 0 &&
(def->iommus[0]->intremap == VIR_TRISTATE_SWITCH_ON ||
qemuDomainNeedsIOMMUWithEIM(def)) &&
def->features[VIR_DOMAIN_FEATURE_IOAPIC] == VIR_DOMAIN_IOAPIC_NONE) {
diff --git a/tests/qemuxmlconfdata/iommu-smmuv3-pci-bus-single.aarch64-latest.args b/tests/qemuxmlconfdata/iommu-smmuv3-pci-bus-single.aarch64-latest.args
index 976467e641..34e7bda1c5 100644
--- a/tests/qemuxmlconfdata/iommu-smmuv3-pci-bus-single.aarch64-latest.args
+++ b/tests/qemuxmlconfdata/iommu-smmuv3-pci-bus-single.aarch64-latest.args
@@ -10,7 +10,7 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-guest/.config \
-name guest=guest,debug-threads=on \
-S \
-object '{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/var/lib/libvirt/qemu/domain--1-guest/master-key.aes"}' \
--machine virt,usb=off,gic-version=2,iommu=smmuv3,dump-guest-core=off,memory-backend=mach-virt.ram,acpi=off \
+-machine virt,usb=off,gic-version=2,dump-guest-core=off,memory-backend=mach-virt.ram,acpi=off \
-accel tcg \
-cpu cortex-a15 \
-m size=1048576k \
--
2.52.0

View File

@ -0,0 +1,65 @@
From 8b337691d19e1619f711b437b2618ac269e5e12f Mon Sep 17 00:00:00 2001
Message-ID: <8b337691d19e1619f711b437b2618ac269e5e12f.1772815313.git.jdenemar@redhat.com>
From: Andrea Bolognani <abologna@redhat.com>
Date: Fri, 21 Nov 2025 19:32:31 +0100
Subject: [PATCH] qemu: Validate presence of uefi-vars device
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The use of varstore requires the uefi-vars device to be present
in the QEMU binary.
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
(cherry picked from commit bd3504651759afac45e76b73912952bf2af2bcfa)
https://issues.redhat.com/browse/RHEL-82645
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
---
src/qemu/qemu_validate.c | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c
index aa441188cb..25e1b9cf58 100644
--- a/src/qemu/qemu_validate.c
+++ b/src/qemu/qemu_validate.c
@@ -754,6 +754,23 @@ qemuValidateDomainDefNvram(const virDomainDef *def,
}
+static int
+qemuValidateDomainDefVarstore(const virDomainDef *def,
+ virQEMUCaps *qemuCaps)
+{
+ if (!def->os.varstore)
+ return 0;
+
+ if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_UEFI_VARS)) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("The uefi-vars device is not supported by this QEMU binary"));
+ return -1;
+ }
+
+ return 0;
+}
+
+
static int
qemuValidateDomainDefBoot(const virDomainDef *def,
virQEMUCaps *qemuCaps)
@@ -797,6 +814,9 @@ qemuValidateDomainDefBoot(const virDomainDef *def,
if (qemuValidateDomainDefNvram(def, qemuCaps) < 0)
return -1;
+
+ if (qemuValidateDomainDefVarstore(def, qemuCaps) < 0)
+ return -1;
}
for (i = 0; i < def->os.nacpiTables; i++) {
--
2.53.0

View File

@ -0,0 +1,58 @@
From 2674cc2e58f98439fe72e4d832e6e2e9b41a614f Mon Sep 17 00:00:00 2001
Message-ID: <2674cc2e58f98439fe72e4d832e6e2e9b41a614f.1771336681.git.jdenemar@redhat.com>
From: Peter Krempa <pkrempa@redhat.com>
Date: Thu, 11 Dec 2025 19:26:40 +0100
Subject: [PATCH] qemu: capabilities: Introduce
QEMU_CAPS_DEVICE_SCSI_BLOCK_MIGRATE_PR
Introduce capability for persisten migration control support.
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit b0edb7eb9b819e0560bb7d65b4e0c89082b3b43b)
https://issues.redhat.com/browse/RHEL-140614 [rhel-9.8]
https://issues.redhat.com/browse/RHEL-135115 [rhel-10.2]
Conflicts:
- Commit befdd44bf836c3ba46e46d57b587127e12736591 adding
QEMU_CAPS_VIRTIO_IOMMU_AW_BITS was not backported
---
src/qemu/qemu_capabilities.c | 2 ++
src/qemu/qemu_capabilities.h | 1 +
2 files changed, 3 insertions(+)
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index 1efb77d03b..2c8bd62c99 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -755,6 +755,7 @@ VIR_ENUM_IMPL(virQEMUCaps,
"disk-timed-stats", /* QEMU_CAPS_DISK_TIMED_STATS */
"query-accelerators", /* QEMU_CAPS_QUERY_ACCELERATORS */
"mshv", /* QEMU_CAPS_MSHV */
+ "scsi-block.migrate-pr", /* QEMU_CAPS_DEVICE_SCSI_BLOCK_MIGRATE_PR */
);
@@ -1536,6 +1537,7 @@ static struct virQEMUCapsDevicePropsFlags virQEMUCapsDevicePropsSCSIDisk[] = {
};
static struct virQEMUCapsDevicePropsFlags virQEMUCapsDevicePropsSCSIBlock[] = {
+ { "migrate-pr", QEMU_CAPS_DEVICE_SCSI_BLOCK_MIGRATE_PR, NULL },
};
static struct virQEMUCapsDevicePropsFlags virQEMUCapsDevicePropsSCSIGeneric[] = {
diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
index f180844e66..0c76f2edda 100644
--- a/src/qemu/qemu_capabilities.h
+++ b/src/qemu/qemu_capabilities.h
@@ -730,6 +730,7 @@ typedef enum { /* virQEMUCapsFlags grouping marker for syntax-check */
QEMU_CAPS_DISK_TIMED_STATS, /* timed stats support ('stats-intervals' property of disk frontends) */
QEMU_CAPS_QUERY_ACCELERATORS, /* query-accelerators command */
QEMU_CAPS_MSHV, /* -accel mshv */
+ QEMU_CAPS_DEVICE_SCSI_BLOCK_MIGRATE_PR, /* persistent reservation migration support */
QEMU_CAPS_LAST /* this must always be the last item */
} virQEMUCapsFlags;
--
2.53.0

View File

@ -1,128 +0,0 @@
From c30b3dd904c094c478c5b362de6b3580379edd8b Mon Sep 17 00:00:00 2001
Message-ID: <c30b3dd904c094c478c5b362de6b3580379edd8b.1720800605.git.jdenemar@redhat.com>
From: =?UTF-8?q?J=C3=A1n=20Tomko?= <jtomko@redhat.com>
Date: Thu, 4 Jul 2024 15:54:29 +0200
Subject: [PATCH] qemu: do not use deprecated options for new virtiofsd
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Use the to-be-introduced virtiofsd capability to mark whether
new options are safe to use.
Depends on:
https://gitlab.com/virtio-fs/virtiofsd/-/merge_requests/231
https://issues.redhat.com/browse/RHEL-7108
Signed-off-by: Ján Tomko <jtomko@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit 8dc04cafecd2432c071c73366e4c6eb3b7bff495)
https://issues.redhat.com/browse/RHEL-7108
Signed-off-by: Ján Tomko <jtomko@redhat.com>
---
src/qemu/qemu_virtiofs.c | 83 +++++++++++++++++++++++++++-------------
1 file changed, 57 insertions(+), 26 deletions(-)
diff --git a/src/qemu/qemu_virtiofs.c b/src/qemu/qemu_virtiofs.c
index 0df8d67b1b..0e3c7dbb58 100644
--- a/src/qemu/qemu_virtiofs.c
+++ b/src/qemu/qemu_virtiofs.c
@@ -139,36 +139,67 @@ qemuVirtioFSBuildCommandLine(virQEMUDriverConfig *cfg,
virCommandPassFD(cmd, *fd, VIR_COMMAND_PASS_FD_CLOSE_PARENT);
*fd = -1;
- virCommandAddArg(cmd, "-o");
- virBufferAddLit(&opts, "source=");
- virQEMUBuildBufferEscapeComma(&opts, fs->src->path);
- if (fs->cache)
- virBufferAsprintf(&opts, ",cache=%s", virDomainFSCacheModeTypeToString(fs->cache));
- if (fs->sandbox)
- virBufferAsprintf(&opts, ",sandbox=%s", virDomainFSSandboxModeTypeToString(fs->sandbox));
-
- if (fs->xattr == VIR_TRISTATE_SWITCH_ON)
- virBufferAddLit(&opts, ",xattr");
- else if (fs->xattr == VIR_TRISTATE_SWITCH_OFF)
- virBufferAddLit(&opts, ",no_xattr");
-
- if (fs->flock == VIR_TRISTATE_SWITCH_ON)
- virBufferAddLit(&opts, ",flock");
- else if (fs->flock == VIR_TRISTATE_SWITCH_OFF)
- virBufferAddLit(&opts, ",no_flock");
-
- if (fs->posix_lock == VIR_TRISTATE_SWITCH_ON)
- virBufferAddLit(&opts, ",posix_lock");
- else if (fs->posix_lock == VIR_TRISTATE_SWITCH_OFF)
- virBufferAddLit(&opts, ",no_posix_lock");
-
- virCommandAddArgBuffer(cmd, &opts);
+ if (virBitmapIsBitSet(fs->caps, QEMU_VHOST_USER_FS_FEATURE_SEPARATE_OPTIONS)) {
+ /* Note that this option format is used by the Rust version of the daemon
+ * since v1.0.0, which is way longer than the capability existed.
+ * The -o style of options can be removed once we bump the minimal
+ * QEMU version to 8.0.0, which dropped the C virtiofsd daemon */
+ virCommandAddArg(cmd, "--shared-dir");
+ virCommandAddArg(cmd, fs->src->path);
+
+ if (fs->cache) {
+ virCommandAddArg(cmd, "--cache");
+ virCommandAddArg(cmd, virDomainFSCacheModeTypeToString(fs->cache));
+ }
+ if (fs->sandbox) {
+ virCommandAddArg(cmd, "--sandbox");
+ virCommandAddArg(cmd, virDomainFSSandboxModeTypeToString(fs->sandbox));
+ }
+
+ if (fs->xattr == VIR_TRISTATE_SWITCH_ON)
+ virCommandAddArg(cmd, "--xattr");
+
+ if (fs->posix_lock != VIR_TRISTATE_SWITCH_ABSENT ||
+ fs->flock != VIR_TRISTATE_SWITCH_ABSENT) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("locking options are not supported by this virtiofsd"));
+ return NULL;
+ }
+ } else {
+ virCommandAddArg(cmd, "-o");
+ virBufferAddLit(&opts, "source=");
+ virQEMUBuildBufferEscapeComma(&opts, fs->src->path);
+ if (fs->cache)
+ virBufferAsprintf(&opts, ",cache=%s", virDomainFSCacheModeTypeToString(fs->cache));
+ if (fs->sandbox)
+ virBufferAsprintf(&opts, ",sandbox=%s", virDomainFSSandboxModeTypeToString(fs->sandbox));
+
+ if (fs->xattr == VIR_TRISTATE_SWITCH_ON)
+ virBufferAddLit(&opts, ",xattr");
+ else if (fs->xattr == VIR_TRISTATE_SWITCH_OFF)
+ virBufferAddLit(&opts, ",no_xattr");
+
+ if (fs->flock == VIR_TRISTATE_SWITCH_ON)
+ virBufferAddLit(&opts, ",flock");
+ else if (fs->flock == VIR_TRISTATE_SWITCH_OFF)
+ virBufferAddLit(&opts, ",no_flock");
+
+ if (fs->posix_lock == VIR_TRISTATE_SWITCH_ON)
+ virBufferAddLit(&opts, ",posix_lock");
+ else if (fs->posix_lock == VIR_TRISTATE_SWITCH_OFF)
+ virBufferAddLit(&opts, ",no_posix_lock");
+
+ virCommandAddArgBuffer(cmd, &opts);
+ }
if (fs->thread_pool_size >= 0)
virCommandAddArgFormat(cmd, "--thread-pool-size=%i", fs->thread_pool_size);
- if (cfg->virtiofsdDebug)
- virCommandAddArg(cmd, "-d");
+ if (cfg->virtiofsdDebug) {
+ if (virBitmapIsBitSet(fs->caps, QEMU_VHOST_USER_FS_FEATURE_SEPARATE_OPTIONS))
+ virCommandAddArgList(cmd, "--log-level", "debug", NULL);
+ else
+ virCommandAddArg(cmd, "-d");
+ }
for (i = 0; i < fs->idmap.nuidmap; i++) {
virCommandAddArgFormat(cmd, "--uid-map=:%u:%u:%u:",
--
2.45.2

View File

@ -1,208 +0,0 @@
From 26c0a729f2ae6dcd932a42bd437fc76da9e6b2cc Mon Sep 17 00:00:00 2001
Message-ID: <26c0a729f2ae6dcd932a42bd437fc76da9e6b2cc.1720800605.git.jdenemar@redhat.com>
From: =?UTF-8?q?J=C3=A1n=20Tomko?= <jtomko@redhat.com>
Date: Thu, 4 Jul 2024 15:54:28 +0200
Subject: [PATCH] qemu: fill capabilities for virtiofsd
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Run the daemon with --print-capabilities first, to see what it supports.
Signed-off-by: Ján Tomko <jtomko@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit 730eaafaace6b9202f9f694b732196299a0baec2)
https://issues.redhat.com/browse/RHEL-7108
https://issues.redhat.com/browse/RHEL-40135
Signed-off-by: Ján Tomko <jtomko@redhat.com>
---
src/conf/domain_conf.c | 1 +
src/conf/domain_conf.h | 1 +
src/qemu/qemu_vhost_user.c | 58 +++++++++++++++++++
src/qemu/qemu_vhost_user.h | 11 ++++
src/qemu/qemu_virtiofs.c | 9 ++-
.../qemu/vhost-user/50-qemu-virtiofsd.json | 2 +-
tests/qemuxmlconftest.c | 2 +
7 files changed, 81 insertions(+), 3 deletions(-)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 8a3c63b1fc..1523341b34 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -2600,6 +2600,7 @@ void virDomainFSDefFree(virDomainFSDef *def)
g_free(def->sock);
g_free(def->idmap.uidmap);
g_free(def->idmap.gidmap);
+ virBitmapFree(def->caps);
g_free(def);
}
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 2818a9f1f5..b3a0d26cde 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -899,6 +899,7 @@ struct _virDomainFSDef {
virDomainIdMapDef idmap;
virDomainVirtioOptions *virtio;
virObject *privateData;
+ virBitmap *caps;
};
diff --git a/src/qemu/qemu_vhost_user.c b/src/qemu/qemu_vhost_user.c
index 0294daab80..de3ef640a3 100644
--- a/src/qemu/qemu_vhost_user.c
+++ b/src/qemu/qemu_vhost_user.c
@@ -22,6 +22,7 @@
#include "qemu_vhost_user.h"
#include "qemu_interop_config.h"
+#include "virbitmap.h"
#include "virjson.h"
#include "virlog.h"
#include "viralloc.h"
@@ -90,6 +91,12 @@ VIR_ENUM_IMPL(qemuVhostUserGPUFeature,
"render-node",
);
+VIR_ENUM_IMPL(qemuVhostUserFSFeature,
+ QEMU_VHOST_USER_FS_FEATURE_LAST,
+ "migrate-precopy",
+ "separate-options",
+);
+
typedef struct _qemuVhostUserGPU qemuVhostUserGPU;
struct _qemuVhostUserGPU {
size_t nfeatures;
@@ -414,6 +421,52 @@ qemuVhostUserFillDomainGPU(virQEMUDriver *driver,
return ret;
}
+int
+qemuVhostUserFillFSCapabilities(virBitmap **caps,
+ const char *binary)
+{
+ g_autoptr(virJSONValue) doc = NULL;
+ g_autofree char *output = NULL;
+ g_autoptr(virCommand) cmd = NULL;
+ virJSONValue *featuresJSON;
+ size_t nfeatures;
+ size_t i;
+ g_autoptr(virBitmap) features = NULL;
+
+ cmd = virCommandNewArgList(binary, "--print-capabilities", NULL);
+ virCommandSetOutputBuffer(cmd, &output);
+ if (virCommandRun(cmd, NULL) < 0)
+ return -2;
+
+ if (!(doc = virJSONValueFromString(output))) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("unable to parse json capabilities '%1$s'"),
+ binary);
+ return -1;
+ }
+
+ /* Older virtiofsd did not print any features */
+ if (!(featuresJSON = virJSONValueObjectGetArray(doc, "features")))
+ return 0;
+
+ features = virBitmapNew(0);
+ nfeatures = virJSONValueArraySize(featuresJSON);
+
+ for (i = 0; i < nfeatures; i++) {
+ virJSONValue *item = virJSONValueArrayGet(featuresJSON, i);
+ const char *tmpStr = virJSONValueGetString(item);
+ int tmp;
+
+ if ((tmp = qemuVhostUserFSFeatureTypeFromString(tmpStr)) < 0) {
+ VIR_DEBUG("ignoring unknown virtiofs feature '%s'", tmpStr);
+ continue;
+ }
+ virBitmapSetBitExpand(features, tmp);
+ }
+
+ *caps = g_steal_pointer(&features);
+ return 0;
+}
int
qemuVhostUserFillDomainFS(virQEMUDriver *driver,
@@ -435,6 +488,11 @@ qemuVhostUserFillDomainFS(virQEMUDriver *driver,
continue;
fs->binary = g_strdup(vu->binary);
+
+ /* skip binaries that can't report their capabilities */
+ if (qemuVhostUserFillFSCapabilities(&fs->caps,
+ vu->binary) == -1)
+ continue;
break;
}
diff --git a/src/qemu/qemu_vhost_user.h b/src/qemu/qemu_vhost_user.h
index d1aa6ca189..c39fbfebe8 100644
--- a/src/qemu/qemu_vhost_user.h
+++ b/src/qemu/qemu_vhost_user.h
@@ -46,3 +46,14 @@ qemuVhostUserFillDomainGPU(virQEMUDriver *driver,
int
qemuVhostUserFillDomainFS(virQEMUDriver *driver,
virDomainFSDef *fs);
+
+int
+qemuVhostUserFillFSCapabilities(virBitmap **caps,
+ const char *binary);
+typedef enum {
+ QEMU_VHOST_USER_FS_FEATURE_MIGRATE_PRECOPY = 0,
+ QEMU_VHOST_USER_FS_FEATURE_SEPARATE_OPTIONS,
+ QEMU_VHOST_USER_FS_FEATURE_LAST
+} qemuVhostUserFSFeature;
+
+VIR_ENUM_DECL(qemuVhostUserFSFeature);
diff --git a/src/qemu/qemu_virtiofs.c b/src/qemu/qemu_virtiofs.c
index 78897d8177..0df8d67b1b 100644
--- a/src/qemu/qemu_virtiofs.c
+++ b/src/qemu/qemu_virtiofs.c
@@ -446,8 +446,13 @@ qemuVirtioFSPrepareDomain(virQEMUDriver *driver,
if (fs->sock)
return 0;
- if (!fs->binary && qemuVhostUserFillDomainFS(driver, fs) < 0)
- return -1;
+ if (fs->binary) {
+ if (qemuVhostUserFillFSCapabilities(&fs->caps, fs->binary) < 0)
+ return -1;
+ } else {
+ if (qemuVhostUserFillDomainFS(driver, fs) < 0)
+ return -1;
+ }
if (!driver->privileged && !fs->idmap.uidmap) {
if (qemuVirtioFSPrepareIdMap(fs) < 0)
diff --git a/tests/qemuvhostuserdata/usr/share/qemu/vhost-user/50-qemu-virtiofsd.json b/tests/qemuvhostuserdata/usr/share/qemu/vhost-user/50-qemu-virtiofsd.json
index b908bc6b30..5cf2c986f8 100644
--- a/tests/qemuvhostuserdata/usr/share/qemu/vhost-user/50-qemu-virtiofsd.json
+++ b/tests/qemuvhostuserdata/usr/share/qemu/vhost-user/50-qemu-virtiofsd.json
@@ -1,5 +1,5 @@
{
"description": "virtiofsd vhost-user-fs",
"type": "fs",
- "binary": "/usr/libexec/qemu/vhost-user/test-vhost-user-gpu"
+ "binary": "/usr/libexec/qemu/vhost-user/test-virtiofsd"
}
diff --git a/tests/qemuxmlconftest.c b/tests/qemuxmlconftest.c
index 8e0d47c6fd..a3a399e16c 100644
--- a/tests/qemuxmlconftest.c
+++ b/tests/qemuxmlconftest.c
@@ -1079,6 +1079,8 @@ mymain(void)
virFileWrapperAddPrefix("/usr/libexec/qemu/vhost-user",
abs_srcdir "/qemuvhostuserdata/usr/libexec/qemu/vhost-user");
+ virFileWrapperAddPrefix("/usr/libexec/virtiofsd",
+ abs_srcdir "/qemuvhostuserdata/usr/libexec/qemu/vhost-user/test-virtiofsd");
if (!(conn = virGetConnect()))
return EXIT_FAILURE;
--
2.45.2

View File

@ -0,0 +1,147 @@
From 64ae2c71b95cd25fb1e18fbc68ddbc814f3de8ca Mon Sep 17 00:00:00 2001
Message-ID: <64ae2c71b95cd25fb1e18fbc68ddbc814f3de8ca.1770203422.git.jdenemar@redhat.com>
From: Peter Krempa <pkrempa@redhat.com>
Date: Tue, 27 Jan 2026 17:00:10 +0100
Subject: [PATCH] qemu: migration: Always offer block dirty bitmaps during
migration
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Until now block dirty bitmaps were offered to destination only if
non-shared storage migration was enabled.
Upcoming patches will want to support it also in cases when storage is
shared but the destination has a qcow2 overlay using the 'data_file'
feature where the qcow2 overlay is not actually shared.
To support that we'll now always offer bitmaps for migration. The
destination can then decide (using existing logic) to pick only the
ones that are not present in the image on destination, which is how
it was supposed to work even now.
The patch removes all the flag checks and simply offers bitmaps in any
case. The overhead incurred by this is one 'query-named-block-nodes'
call to qemu.
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
(cherry picked from commit a4f610ff3fe190058f18baea18b095d0bc69441b)
https://issues.redhat.com/browse/RHEL-145769 [rhel-10.2]
https://issues.redhat.com/browse/RHEL-145770 [rhel-9.8]
---
src/qemu/qemu_migration.c | 28 +++++++---------------------
1 file changed, 7 insertions(+), 21 deletions(-)
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index 723e131c98..755b9a5e1a 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -2580,16 +2580,13 @@ qemuMigrationAnyConnectionClosed(virDomainObj *vm,
* qemuMigrationSrcBeginPhaseBlockDirtyBitmaps:
* @mig: migration cookie struct
* @vm: domain object
- * @migrate_disks: disks which are being migrated
- * @nmigrage_disks: number of @migrate_disks
*
* Enumerates block dirty bitmaps on disks which will undergo storage migration
* and fills them into @mig to be offered to the destination.
*/
static int
qemuMigrationSrcBeginPhaseBlockDirtyBitmaps(qemuMigrationCookie *mig,
- virDomainObj *vm,
- const char **migrate_disks)
+ virDomainObj *vm)
{
GSList *disks = NULL;
@@ -2611,9 +2608,6 @@ qemuMigrationSrcBeginPhaseBlockDirtyBitmaps(qemuMigrationCookie *mig,
if (!nodedata)
continue;
- if (!qemuMigrationAnyCopyDisk(diskdef, migrate_disks))
- continue;
-
for (j = 0; j < nodedata->nbitmaps; j++) {
qemuMigrationBlockDirtyBitmapsDiskBitmap *bitmap;
@@ -2680,7 +2674,6 @@ qemuMigrationSrcBeginXML(virDomainObj *vm,
char **cookieout,
int *cookieoutlen,
unsigned int cookieFlags,
- const char **migrate_disks,
unsigned int flags)
{
qemuDomainObjPrivate *priv = vm->privateData;
@@ -2696,8 +2689,7 @@ qemuMigrationSrcBeginXML(virDomainObj *vm,
if (!(mig = qemuMigrationCookieNew(vm->def, priv->origname)))
return NULL;
- if (cookieFlags & QEMU_MIGRATION_COOKIE_NBD &&
- qemuMigrationSrcBeginPhaseBlockDirtyBitmaps(mig, vm, migrate_disks) < 0)
+ if (qemuMigrationSrcBeginPhaseBlockDirtyBitmaps(mig, vm) < 0)
return NULL;
if (qemuMigrationCookieFormat(mig, driver, vm,
@@ -2879,8 +2871,7 @@ qemuMigrationSrcBeginPhase(virQEMUDriver *driver,
return NULL;
return qemuMigrationSrcBeginXML(vm, xmlin,
- cookieout, cookieoutlen, cookieFlags,
- migrate_disks, flags);
+ cookieout, cookieoutlen, cookieFlags, flags);
}
@@ -2969,8 +2960,7 @@ qemuMigrationSrcBeginResume(virDomainObj *vm,
return NULL;
}
- return qemuMigrationSrcBeginXML(vm, xmlin,
- cookieout, cookieoutlen, 0, NULL, flags);
+ return qemuMigrationSrcBeginXML(vm, xmlin, cookieout, cookieoutlen, 0, flags);
}
@@ -4752,7 +4742,6 @@ qemuMigrationSrcRunPrepareBlockDirtyBitmaps(virDomainObj *vm,
/* For VIR_MIGRATE_NON_SHARED_INC we can migrate the bitmaps directly,
* otherwise we must create merged bitmaps from the whole chain */
-
if (!(flags & VIR_MIGRATE_NON_SHARED_INC) &&
qemuMigrationSrcRunPrepareBlockDirtyBitmapsMerge(vm, mig) < 0)
return -1;
@@ -4943,7 +4932,7 @@ qemuMigrationSrcRun(virQEMUDriver *driver,
VIR_AUTOCLOSE fd = -1;
unsigned long restore_max_bandwidth = priv->migMaxBandwidth;
virErrorPtr orig_err = NULL;
- unsigned int cookieFlags = 0;
+ unsigned int cookieFlags = QEMU_MIGRATION_COOKIE_BLOCK_DIRTY_BITMAPS;
bool abort_on_error = !!(flags & VIR_MIGRATE_ABORT_ON_ERROR);
bool storageMigration = flags & (VIR_MIGRATE_NON_SHARED_DISK | VIR_MIGRATE_NON_SHARED_INC);
bool cancel = false;
@@ -4967,10 +4956,8 @@ qemuMigrationSrcRun(virQEMUDriver *driver,
storageMigration = qemuMigrationHasAnyStorageMigrationDisks(vm->def,
migrate_disks);
- if (storageMigration) {
+ if (storageMigration)
cookieFlags |= QEMU_MIGRATION_COOKIE_NBD;
- cookieFlags |= QEMU_MIGRATION_COOKIE_BLOCK_DIRTY_BITMAPS;
- }
if (virLockManagerPluginUsesState(driver->lockManager) &&
!cookieout) {
@@ -5004,8 +4991,7 @@ qemuMigrationSrcRun(virQEMUDriver *driver,
cookiein, cookieinlen,
cookieFlags |
QEMU_MIGRATION_COOKIE_GRAPHICS |
- QEMU_MIGRATION_COOKIE_CAPS |
- QEMU_MIGRATION_COOKIE_BLOCK_DIRTY_BITMAPS);
+ QEMU_MIGRATION_COOKIE_CAPS);
if (!mig)
goto error;
--
2.52.0

View File

@ -1,52 +0,0 @@
From 5f73e98cc870b13a053fd99d4d2707fed50e57d0 Mon Sep 17 00:00:00 2001
Message-ID: <5f73e98cc870b13a053fd99d4d2707fed50e57d0.1720800605.git.jdenemar@redhat.com>
From: =?UTF-8?q?J=C3=A1n=20Tomko?= <jtomko@redhat.com>
Date: Thu, 4 Jul 2024 15:54:30 +0200
Subject: [PATCH] qemu: migration: allow migration for virtiofs
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Allow migration if the "migrate-precopy" capability is present or
libvirt is not the one running the virtiofs daemon.
Signed-off-by: Ján Tomko <jtomko@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit d94b31a68ab94f27f8a1d6d216817b49881c38ae)
https://issues.redhat.com/browse/RHEL-40135
Signed-off-by: Ján Tomko <jtomko@redhat.com>
---
src/qemu/qemu_migration.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index 26c082fc08..4fd7a0aafb 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -39,6 +39,7 @@
#include "qemu_slirp.h"
#include "qemu_block.h"
#include "qemu_tpm.h"
+#include "qemu_vhost_user.h"
#include "domain_audit.h"
#include "virlog.h"
@@ -1576,8 +1577,12 @@ qemuMigrationSrcIsAllowed(virDomainObj *vm,
virDomainFSDef *fs = vm->def->fss[i];
if (fs->fsdriver == VIR_DOMAIN_FS_DRIVER_TYPE_VIRTIOFS) {
- virReportError(VIR_ERR_OPERATION_INVALID, "%s",
- _("migration with virtiofs device is not supported"));
+ if (fs->sock ||
+ virBitmapIsBitSet(fs->caps, QEMU_VHOST_USER_FS_FEATURE_MIGRATE_PRECOPY))
+ continue;
+
+ virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
+ _("migration with this virtiofs device is not supported"));
return false;
}
}
--
2.45.2

View File

@ -0,0 +1,182 @@
From 99b1b6fda9b4e098a7bbbbb44e02064c57bff558 Mon Sep 17 00:00:00 2001
Message-ID: <99b1b6fda9b4e098a7bbbbb44e02064c57bff558.1771336681.git.jdenemar@redhat.com>
From: Peter Krempa <pkrempa@redhat.com>
Date: Thu, 11 Dec 2025 18:38:12 +0100
Subject: [PATCH] qemu: monitor: Add handlers for 'block-latency-histogram-set'
Add QMP monitor code for setting up latency histogram configuration.
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit ad4830ce6844b75800685ea85b15a53b8dbc5ac6)
https://issues.redhat.com/browse/RHEL-147866 [rhel-9.8]
https://issues.redhat.com/browse/RHEL-131335 [rhel-10.2]
---
src/qemu/qemu_monitor.c | 21 +++++++++++++
src/qemu/qemu_monitor.h | 9 ++++++
src/qemu/qemu_monitor_json.c | 60 ++++++++++++++++++++++++++++++++++++
src/qemu/qemu_monitor_json.h | 9 ++++++
tests/qemumonitorjsontest.c | 9 ++++++
5 files changed, 108 insertions(+)
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index cdd08004fb..3d7477c01c 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -4612,3 +4612,24 @@ qemuMonitorBlockdevSetActive(qemuMonitor *mon,
return qemuMonitorJSONBlockdevSetActive(mon, nodename, active);
}
+
+
+int
+qemuMonitorBlockLatencyHistogramSet(qemuMonitor *mon,
+ const char *id,
+ unsigned int *boundaries,
+ unsigned int *boundaries_read,
+ unsigned int *boundaries_write,
+ unsigned int *boundaries_zone,
+ unsigned int *boundaries_flush)
+{
+ QEMU_CHECK_MONITOR(mon);
+ VIR_DEBUG("id='%s'", id);
+
+ return qemuMonitorJSONBlockLatencyHistogramSet(mon, id,
+ boundaries,
+ boundaries_read,
+ boundaries_write,
+ boundaries_zone,
+ boundaries_flush);
+}
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index 238f7be875..bbe400003a 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -1988,3 +1988,12 @@ int
qemuMonitorBlockdevSetActive(qemuMonitor *mon,
const char *nodename,
bool active);
+
+int
+qemuMonitorBlockLatencyHistogramSet(qemuMonitor *mon,
+ const char *id,
+ unsigned int *boundaries,
+ unsigned int *boundaries_read,
+ unsigned int *boundaries_write,
+ unsigned int *boundaries_zone,
+ unsigned int *boundaries_flush);
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index edeea22ee0..45f690d9e2 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -9130,3 +9130,63 @@ qemuMonitorJSONBlockdevSetActive(qemuMonitor *mon,
return qemuMonitorJSONCheckError(cmd, reply);
}
+
+
+static virJSONValue *
+qemuMonitorJSONBlockLatencyHistogramBoundary(unsigned int *bound)
+{
+ g_autoptr(virJSONValue) ret = virJSONValueNewArray();
+
+ if (!bound)
+ return NULL;
+
+ for (; *bound > 0; bound++) {
+ g_autoptr(virJSONValue) val = virJSONValueNewNumberUint(*bound);
+
+ /* the only error is if the first argument is not an array */
+ ignore_value(virJSONValueArrayAppend(ret, &val));
+ }
+
+ return g_steal_pointer(&ret);
+}
+
+
+int
+qemuMonitorJSONBlockLatencyHistogramSet(qemuMonitor *mon,
+ const char *id,
+ unsigned int *boundaries,
+ unsigned int *boundaries_read,
+ unsigned int *boundaries_write,
+ unsigned int *boundaries_zone,
+ unsigned int *boundaries_flush)
+{
+ g_autoptr(virJSONValue) cmd = NULL;
+ g_autoptr(virJSONValue) reply = NULL;
+
+ g_autoptr(virJSONValue) bound = NULL;
+ g_autoptr(virJSONValue) bound_read = NULL;
+ g_autoptr(virJSONValue) bound_write = NULL;
+ g_autoptr(virJSONValue) bound_zone = NULL;
+ g_autoptr(virJSONValue) bound_flush = NULL;
+
+ bound = qemuMonitorJSONBlockLatencyHistogramBoundary(boundaries);
+ bound_read = qemuMonitorJSONBlockLatencyHistogramBoundary(boundaries_read);
+ bound_write = qemuMonitorJSONBlockLatencyHistogramBoundary(boundaries_write);
+ bound_zone = qemuMonitorJSONBlockLatencyHistogramBoundary(boundaries_zone);
+ bound_flush = qemuMonitorJSONBlockLatencyHistogramBoundary(boundaries_flush);
+
+ if (!(cmd = qemuMonitorJSONMakeCommand("block-latency-histogram-set",
+ "s:id", id,
+ "A:boundaries", &bound,
+ "A:boundaries-read", &bound_read,
+ "A:boundaries-write", &bound_write,
+ "A:boundaries-zap", &bound_zone,
+ "A:boundaries-flush", &bound_flush,
+ NULL)))
+ return -1;
+
+ if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
+ return -1;
+
+ return qemuMonitorJSONCheckError(cmd, reply);
+}
diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h
index db9160eb68..b418f70048 100644
--- a/src/qemu/qemu_monitor_json.h
+++ b/src/qemu/qemu_monitor_json.h
@@ -815,3 +815,12 @@ int
qemuMonitorJSONBlockdevSetActive(qemuMonitor *mon,
const char *nodename,
bool active);
+
+int
+qemuMonitorJSONBlockLatencyHistogramSet(qemuMonitor *mon,
+ const char *id,
+ unsigned int *boundaries,
+ unsigned int *boundaries_read,
+ unsigned int *boundaries_write,
+ unsigned int *boundaries_zone,
+ unsigned int *boundaries_flush);
diff --git a/tests/qemumonitorjsontest.c b/tests/qemumonitorjsontest.c
index bfe81739a7..1c1aaaa586 100644
--- a/tests/qemumonitorjsontest.c
+++ b/tests/qemumonitorjsontest.c
@@ -1130,6 +1130,14 @@ GEN_TEST_FUNC(qemuMonitorJSONSetAction,
GEN_TEST_FUNC(qemuMonitorJSONSetLaunchSecurityState, "sev_secret_header",
"sev_secret", 0, true)
+unsigned int testHistogramBoundaries[] = {10, 30, 50, 0};
+GEN_TEST_FUNC(qemuMonitorJSONBlockLatencyHistogramSet, "devid",
+ testHistogramBoundaries,
+ testHistogramBoundaries,
+ testHistogramBoundaries,
+ testHistogramBoundaries,
+ testHistogramBoundaries)
+
static int
testQemuMonitorJSONqemuMonitorJSONNBDServerStart(const void *opaque)
{
@@ -2958,6 +2966,7 @@ mymain(void)
DO_TEST_GEN(qemuMonitorJSONBlockJobCancel);
DO_TEST_GEN(qemuMonitorJSONSetAction);
DO_TEST_GEN(qemuMonitorJSONSetLaunchSecurityState);
+ DO_TEST_GEN(qemuMonitorJSONBlockLatencyHistogramSet);
DO_TEST(qemuMonitorJSONGetBalloonInfo);
DO_TEST(qemuMonitorJSONGetBlockInfo);
DO_TEST(qemuMonitorJSONGetAllBlockStatsInfo);
--
2.53.0

View File

@ -0,0 +1,173 @@
From 0722d1d58171ca59ec1852026cf6df0faa0d9312 Mon Sep 17 00:00:00 2001
Message-ID: <0722d1d58171ca59ec1852026cf6df0faa0d9312.1770203422.git.jdenemar@redhat.com>
From: Peter Krempa <pkrempa@redhat.com>
Date: Tue, 27 Jan 2026 20:07:32 +0100
Subject: [PATCH] qemu: monitor: Detect list of bitmaps from 'qcow2' format
specific data
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
We currently probe dirty block tracking bitmaps by looking at the loaded
ones ('dirty-bitmaps'). Unfortunately those may not yet be populated on
incoming migration when the image was not yet activated, but we need to
know which ones are stored in the image so that we don't migrate those
explicitly, which would fail.
Load the list of bitmaps in a qcow2 image from the format specific data,
which is already loaded at that point.
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
(cherry picked from commit b2fe3465de1db033e436f38fdd24648c8c884a3d)
https://issues.redhat.com/browse/RHEL-145769 [rhel-10.2]
https://issues.redhat.com/browse/RHEL-145770 [rhel-9.8]
---
src/qemu/qemu_monitor.h | 4 ++++
src/qemu/qemu_monitor_json.c | 17 +++++++++++++++++
tests/qemublocktest.c | 11 +++++++++++
tests/qemublocktestdata/bitmap/snapshots.out | 5 +++++
tests/qemublocktestdata/bitmap/synthetic.out | 4 ++++
5 files changed, 41 insertions(+)
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index d096f474c1..041aa7bc12 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -893,8 +893,12 @@ struct _qemuBlockNamedNodeData {
unsigned long long capacity;
unsigned long long physical;
+ /* Information about change block tracking bitmaps which are active and loaded */
qemuBlockNamedNodeDataBitmap **bitmaps;
size_t nbitmaps;
+ /* With qcow2 we have also a separate list of bitmaps present in the image
+ * but not yet activated, which happens when starting qemu during migration */
+ char **qcow2bitmaps;
/* hash table indexed by snapshot name containing data about snapshots
* (qemuBlockNamedNodeDataSnapshot) */
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index 494d7ef515..401a28ff9a 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -2730,6 +2730,7 @@ qemuMonitorJSONBlockNamedNodeDataFree(qemuBlockNamedNodeData *data)
qemuMonitorJSONBlockNamedNodeDataBitmapFree(data->bitmaps[i]);
g_clear_pointer(&data->snapshots, g_hash_table_unref);
g_free(data->bitmaps);
+ g_strfreev(data->qcow2bitmaps);
g_free(data);
}
G_DEFINE_AUTOPTR_CLEANUP_FUNC(qemuBlockNamedNodeData, qemuMonitorJSONBlockNamedNodeDataFree);
@@ -2854,6 +2855,9 @@ qemuMonitorJSONBlockGetNamedNodeDataWorker(size_t pos G_GNUC_UNUSED,
virJSONValue *qcow2props = virJSONValueObjectGetObject(format_specific, "data");
if (qcow2props) {
+ virJSONValue *bmp;
+ size_t nbmp;
+
if (STREQ_NULLABLE(virJSONValueObjectGetString(qcow2props, "compat"), "0.10"))
ent->qcow2v2 = true;
@@ -2862,6 +2866,19 @@ qemuMonitorJSONBlockGetNamedNodeDataWorker(size_t pos G_GNUC_UNUSED,
ignore_value(virJSONValueObjectGetBoolean(qcow2props, "data-file-raw",
&ent->qcow2dataFileRaw));
+
+ if ((bmp = virJSONValueObjectGetArray(qcow2props, "bitmaps")) &&
+ ((nbmp = virJSONValueArraySize(bmp)) > 0)) {
+ size_t i;
+
+ ent->qcow2bitmaps = g_new0(char *, nbmp + 1);
+
+ for (i = 0; i < nbmp; i++) {
+ virJSONValue *b = virJSONValueArrayGet(bmp, i);
+
+ ent->qcow2bitmaps[i] = g_strdup(virJSONValueObjectGetString(b, "name"));
+ }
+ }
}
}
diff --git a/tests/qemublocktest.c b/tests/qemublocktest.c
index 51d9268cdd..18ec90edf5 100644
--- a/tests/qemublocktest.c
+++ b/tests/qemublocktest.c
@@ -600,6 +600,17 @@ testQemuDetectBitmapsWorker(void *payload,
bitmap->granularity, bitmap->dirtybytes);
}
+ if (data->qcow2bitmaps) {
+ char **b;
+
+ virBufferAddLit(buf, "qcow2 bitmaps:");
+
+ for (b = data->qcow2bitmaps; *b; b++)
+ virBufferAsprintf(buf, " %s", *b);
+
+ virBufferAddLit(buf, "\n");
+ }
+
if (data->snapshots) {
g_autofree virHashKeyValuePair *snaps = virHashGetItems(data->snapshots, NULL, true);
virHashKeyValuePair *n;
diff --git a/tests/qemublocktestdata/bitmap/snapshots.out b/tests/qemublocktestdata/bitmap/snapshots.out
index 29c586be7e..dedd77465c 100644
--- a/tests/qemublocktestdata/bitmap/snapshots.out
+++ b/tests/qemublocktestdata/bitmap/snapshots.out
@@ -4,21 +4,26 @@ libvirt-1-format:
b: record:1 busy:0 persist:1 inconsist:0 gran:65536 dirty:0
c: record:1 busy:0 persist:1 inconsist:0 gran:65536 dirty:0
current: record:1 busy:0 persist:1 inconsist:0 gran:65536 dirty:0
+ qcow2 bitmaps: current c b a d
libvirt-1-storage:
libvirt-2-format:
c: record:1 busy:0 persist:1 inconsist:0 gran:65536 dirty:0
b: record:1 busy:0 persist:1 inconsist:0 gran:65536 dirty:0
a: record:1 busy:0 persist:1 inconsist:0 gran:65536 dirty:0
d: record:1 busy:0 persist:1 inconsist:0 gran:65536 dirty:0
+ qcow2 bitmaps: d a b c
libvirt-2-storage:
libvirt-3-format:
a: record:1 busy:0 persist:1 inconsist:0 gran:65536 dirty:0
b: record:1 busy:0 persist:1 inconsist:0 gran:65536 dirty:0
c: record:1 busy:0 persist:1 inconsist:0 gran:65536 dirty:0
+ qcow2 bitmaps: c b a
libvirt-3-storage:
libvirt-4-format:
a: record:1 busy:0 persist:1 inconsist:0 gran:65536 dirty:0
+ qcow2 bitmaps: a
libvirt-4-storage:
libvirt-5-format:
a: record:1 busy:0 persist:1 inconsist:0 gran:65536 dirty:0
+ qcow2 bitmaps: a
libvirt-5-storage:
diff --git a/tests/qemublocktestdata/bitmap/synthetic.out b/tests/qemublocktestdata/bitmap/synthetic.out
index 2f4ae2b217..0a47a90107 100644
--- a/tests/qemublocktestdata/bitmap/synthetic.out
+++ b/tests/qemublocktestdata/bitmap/synthetic.out
@@ -6,17 +6,21 @@ libvirt-1-format:
top-inactive: record:0 busy:0 persist:1 inconsist:0 gran:65536 dirty:0
top-transient: record:1 busy:0 persist:0 inconsist:0 gran:65536 dirty:0
top-transient-inactive: record:0 busy:0 persist:0 inconsist:0 gran:65536 dirty:0
+ qcow2 bitmaps: current
libvirt-1-storage:
libvirt-2-format:
d: record:1 busy:0 persist:1 inconsist:0 gran:65536 dirty:0
+ qcow2 bitmaps: d
libvirt-2-storage:
libvirt-3-format:
b: record:1 busy:0 persist:0 inconsist:0 gran:65536 dirty:0
c: record:0 busy:0 persist:1 inconsist:0 gran:65536 dirty:0
d: record:1 busy:0 persist:1 inconsist:0 gran:65536 dirty:0
+ qcow2 bitmaps: c b
libvirt-3-storage:
libvirt-4-format:
libvirt-4-storage:
libvirt-5-format:
a: record:1 busy:0 persist:1 inconsist:0 gran:65536 dirty:0
+ qcow2 bitmaps: a
libvirt-5-storage:
--
2.52.0

View File

@ -0,0 +1,168 @@
From e02f5e7ca63bdaaec62c2fffa681b9354bee0792 Mon Sep 17 00:00:00 2001
Message-ID: <e02f5e7ca63bdaaec62c2fffa681b9354bee0792.1771336681.git.jdenemar@redhat.com>
From: Peter Krempa <pkrempa@redhat.com>
Date: Thu, 29 Jan 2026 14:08:18 +0100
Subject: [PATCH] qemu: monitor: Extract block latency histogram stats into
'qemuBlockStats'
Extract the 'rd_latency_histogram', 'wr_latency_histogram',
'zone_append_latency_histogram', and 'flush_latency_histogram' stats
objects into our internal data.
Rather than storing 'boundaries' between bins we store them as start
points.
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit 1c77d396ea9704eae09d7fea160cfd1a897beaf3)
https://issues.redhat.com/browse/RHEL-147866 [rhel-9.8]
https://issues.redhat.com/browse/RHEL-131335 [rhel-10.2]
---
src/qemu/qemu_monitor.c | 20 +++++++++++++
src/qemu/qemu_monitor.h | 18 ++++++++++++
src/qemu/qemu_monitor_json.c | 55 ++++++++++++++++++++++++++++++++++++
3 files changed, 93 insertions(+)
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index 504500c864..cdd08004fb 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -1986,6 +1986,26 @@ qemuBlockStatsFinalize(GObject *object)
g_free(stats->limits);
g_free(stats->timed_stats);
+ if (stats->histogram_read) {
+ g_free(stats->histogram_read->bins);
+ g_free(stats->histogram_read);
+ }
+
+ if (stats->histogram_write) {
+ g_free(stats->histogram_write->bins);
+ g_free(stats->histogram_write);
+ }
+
+ if (stats->histogram_zone) {
+ g_free(stats->histogram_zone->bins);
+ g_free(stats->histogram_zone);
+ }
+
+ if (stats->histogram_flush) {
+ g_free(stats->histogram_flush->bins);
+ g_free(stats->histogram_flush);
+ }
+
G_OBJECT_CLASS(qemu_block_stats_parent_class)->finalize(object);
}
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index 041aa7bc12..238f7be875 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -806,6 +806,18 @@ struct qemuBlockStatsLimits {
};
+struct qemuBlockStatsLatencyHistogramBin {
+ unsigned long long start;
+ unsigned long long value;
+};
+
+
+struct qemuBlockStatsLatencyHistogram {
+ struct qemuBlockStatsLatencyHistogramBin *bins;
+ size_t nbins;
+};
+
+
struct qemuBlockStatsTimed {
unsigned long long interval_length;
@@ -858,6 +870,12 @@ struct _qemuBlockStats {
/* block accounting/timed stats from qemu - one entry per interval configured */
size_t n_timed_stats;
struct qemuBlockStatsTimed *timed_stats;
+
+ /* latency histograms */
+ struct qemuBlockStatsLatencyHistogram *histogram_read;
+ struct qemuBlockStatsLatencyHistogram *histogram_write;
+ struct qemuBlockStatsLatencyHistogram *histogram_zone;
+ struct qemuBlockStatsLatencyHistogram *histogram_flush;
};
G_DECLARE_FINAL_TYPE(qemuBlockStats, qemu_block_stats, QEMU, BLOCK_STATS, GObject);
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index 401a28ff9a..edeea22ee0 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -2425,6 +2425,52 @@ qemuMonitorJSONBlockStatsCollectDataTimed(virJSONValue *timed_stats,
}
+static void
+qemuMonitorJSONBlockStatsCollectDataLatencyHistogram(virJSONValue *stats,
+ const char *histogram_field,
+ struct qemuBlockStatsLatencyHistogram **histogram_data)
+{
+ virJSONValue *hist;
+ virJSONValue *hist_bins;
+ virJSONValue *hist_bounds;
+ g_autofree struct qemuBlockStatsLatencyHistogramBin *bins = NULL;
+ size_t nbins = 0;
+ size_t i;
+
+ if (!(hist = virJSONValueObjectGetObject(stats, histogram_field)))
+ return;
+
+ if (!(hist_bins = virJSONValueObjectGetArray(hist, "bins")) ||
+ !(hist_bounds = virJSONValueObjectGetArray(hist, "boundaries")) ||
+ virJSONValueArraySize(hist_bins) != (virJSONValueArraySize(hist_bounds) + 1)) {
+ VIR_DEBUG("malformed latency histogram container");
+ return;
+ }
+
+ nbins = virJSONValueArraySize(hist_bins);
+ bins = g_new0(struct qemuBlockStatsLatencyHistogramBin, nbins);
+
+ for (i = 0; i < nbins; i++) {
+ virJSONValue *bin = virJSONValueArrayGet(hist_bins, i);
+ virJSONValue *bound = NULL;
+
+ if (i > 0)
+ bound = virJSONValueArrayGet(hist_bounds, i - 1);
+
+ if (!bin ||
+ virJSONValueGetNumberUlong(bin, &(bins[i].value)) < 0 ||
+ (bound && virJSONValueGetNumberUlong(bound, &(bins[i].start)) < 0)) {
+ VIR_DEBUG("malformed latency histogram container");
+ return;
+ }
+ }
+
+ *histogram_data = g_new0(struct qemuBlockStatsLatencyHistogram, 1);
+ (*histogram_data)->bins = g_steal_pointer(&bins);
+ (*histogram_data)->nbins = nbins;
+}
+
+
static qemuBlockStats *
qemuMonitorJSONBlockStatsCollectData(virJSONValue *dev,
int *nstats)
@@ -2469,6 +2515,15 @@ qemuMonitorJSONBlockStatsCollectData(virJSONValue *dev,
bstats->wr_highest_offset_valid = true;
}
+ qemuMonitorJSONBlockStatsCollectDataLatencyHistogram(stats, "rd_latency_histogram",
+ &bstats->histogram_read);
+ qemuMonitorJSONBlockStatsCollectDataLatencyHistogram(stats, "wr_latency_histogram",
+ &bstats->histogram_write);
+ qemuMonitorJSONBlockStatsCollectDataLatencyHistogram(stats, "zone_append_latency_histogram",
+ &bstats->histogram_zone);
+ qemuMonitorJSONBlockStatsCollectDataLatencyHistogram(stats, "flush_latency_histogram",
+ &bstats->histogram_flush);
+
if ((timed_stats = virJSONValueObjectGetArray(stats, "timed_stats")) &&
virJSONValueArraySize(timed_stats) > 0)
qemuMonitorJSONBlockStatsCollectDataTimed(timed_stats, bstats);
--
2.53.0

View File

@ -0,0 +1,247 @@
From 68a23646ba165aa45d3811d626885054ae9d9299 Mon Sep 17 00:00:00 2001
Message-ID: <68a23646ba165aa45d3811d626885054ae9d9299.1770383182.git.jdenemar@redhat.com>
From: Nathan Chen <nathanc@nvidia.com>
Date: Fri, 30 Jan 2026 10:59:15 -0800
Subject: [PATCH] qemu: open VFIO FDs from libvirt backend
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Open VFIO FDs from libvirt backend without exposing
these FDs to XML users, i.e. one per iommufd hostdev
for /dev/vfio/devices/vfioX, and pass the FD to qemu
command line.
Suggested-by: Ján Tomko <jtomko@redhat.com>
Signed-off-by: Nathan Chen <nathanc@nvidia.com>
Reviewed-by: Pavel Hrdina <phrdina@redhat.com>
(cherry picked from commit f6230804727df834da27370e835204672218ab23)
Resolves: https://issues.redhat.com/browse/RHEL-74202
Resolves: https://issues.redhat.com/browse/RHEL-126346
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
---
src/libvirt_private.syms | 1 +
src/qemu/qemu_command.c | 21 +++++++++++
src/qemu/qemu_process.c | 78 ++++++++++++++++++++++++++++++++++++++++
src/util/virpci.c | 39 ++++++++++++++++++++
src/util/virpci.h | 2 ++
5 files changed, 141 insertions(+)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 66261ed6cf..e2a7a16347 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -3162,6 +3162,7 @@ virPCIDeviceGetStubDriverName;
virPCIDeviceGetStubDriverType;
virPCIDeviceGetUnbindFromStub;
virPCIDeviceGetUsedBy;
+virPCIDeviceGetVfioPath;
virPCIDeviceGetVPD;
virPCIDeviceHasPCIExpressLink;
virPCIDeviceIsAssignable;
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 1fb31d1721..83935e82c3 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -4803,6 +4803,18 @@ qemuBuildPCIHostdevDevProps(const virDomainDef *def,
NULL) < 0)
return NULL;
+ if (pcisrc->driver.name == VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_VFIO &&
+ pcisrc->driver.iommufd == VIR_TRISTATE_BOOL_YES) {
+ qemuDomainHostdevPrivate *hostdevPriv = QEMU_DOMAIN_HOSTDEV_PRIVATE(dev);
+
+ if (hostdevPriv->vfioDeviceFd != -1) {
+ g_autofree char *fdstr = g_strdup_printf("%d", hostdevPriv->vfioDeviceFd);
+ if (virJSONValueObjectAdd(&props, "S:fd", fdstr, NULL) < 0)
+ return NULL;
+ hostdevPriv->vfioDeviceFd = -1;
+ }
+ }
+
if (qemuBuildDeviceAddressProps(props, def, dev->info) < 0)
return NULL;
@@ -5247,6 +5259,15 @@ qemuBuildHostdevCommandLine(virCommand *cmd,
if (qemuCommandAddExtDevice(cmd, hostdev->info, def, qemuCaps) < 0)
return -1;
+ if (subsys->u.pci.driver.iommufd == VIR_TRISTATE_BOOL_YES) {
+ qemuDomainHostdevPrivate *hostdevPriv = QEMU_DOMAIN_HOSTDEV_PRIVATE(hostdev);
+
+ if (hostdevPriv->vfioDeviceFd != -1) {
+ virCommandPassFD(cmd, hostdevPriv->vfioDeviceFd,
+ VIR_COMMAND_PASS_FD_CLOSE_PARENT);
+ }
+ }
+
if (!(devprops = qemuBuildPCIHostdevDevProps(def, hostdev)))
return -1;
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 0e50cd1ccc..1ac57a6321 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -103,6 +103,7 @@
#include "storage_source.h"
#include "backup_conf.h"
#include "storage_file_probe.h"
+#include "virpci.h"
#include "logging/log_manager.h"
#include "logging/log_protocol.h"
@@ -7671,6 +7672,81 @@ qemuProcessPrepareHostBackendChardevHotplug(virDomainObj *vm,
return 0;
}
+/**
+ * qemuProcessOpenVfioDeviceFd:
+ * @hostdev: host device definition
+ * @vfioFd: returned file descriptor
+ *
+ * Opens the VFIO device file descriptor for a hostdev.
+ *
+ * Returns: FD on success, -1 on failure
+ */
+static int
+qemuProcessOpenVfioDeviceFd(virDomainHostdevDef *hostdev)
+{
+ g_autofree char *vfioPath = NULL;
+ int fd = -1;
+
+ if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS ||
+ hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("VFIO FD only supported for PCI hostdevs"));
+ return -1;
+ }
+
+ if (virPCIDeviceGetVfioPath(&hostdev->source.subsys.u.pci.addr, &vfioPath) < 0)
+ return -1;
+
+ VIR_DEBUG("Opening VFIO device %s", vfioPath);
+
+ if ((fd = open(vfioPath, O_RDWR | O_CLOEXEC)) < 0) {
+ if (errno == ENOENT) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("VFIO device %1$s not found - ensure device is bound to vfio-pci driver"),
+ vfioPath);
+ } else {
+ virReportSystemError(errno,
+ _("cannot open VFIO device %1$s"), vfioPath);
+ }
+ return -1;
+ }
+
+ VIR_DEBUG("Opened VFIO device FD %d for %s", fd, vfioPath);
+ return fd;
+}
+
+/**
+ * qemuProcessOpenVfioFds:
+ * @vm: domain object
+ *
+ * Opens all necessary VFIO file descriptors for the domain.
+ *
+ * Returns: 0 on success, -1 on failure
+ */
+static int
+qemuProcessOpenVfioFds(virDomainObj *vm)
+{
+ size_t i;
+
+ /* Check if we have any hostdevs that need VFIO FDs */
+ for (i = 0; i < vm->def->nhostdevs; i++) {
+ virDomainHostdevDef *hostdev = vm->def->hostdevs[i];
+ qemuDomainHostdevPrivate *hostdevPriv = QEMU_DOMAIN_HOSTDEV_PRIVATE(hostdev);
+
+ if (hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
+ hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI &&
+ hostdev->source.subsys.u.pci.driver.name == VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_VFIO &&
+ hostdev->source.subsys.u.pci.driver.iommufd == VIR_TRISTATE_BOOL_YES) {
+ /* Open VFIO device FD */
+ hostdevPriv->vfioDeviceFd = qemuProcessOpenVfioDeviceFd(hostdev);
+ if (hostdevPriv->vfioDeviceFd == -1)
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
/**
* qemuProcessPrepareHost:
* @driver: qemu driver
@@ -7726,6 +7802,8 @@ qemuProcessPrepareHost(virQEMUDriver *driver,
hostdev_flags |= VIR_HOSTDEV_COLD_BOOT;
if (qemuHostdevPrepareDomainDevices(driver, vm->def, hostdev_flags) < 0)
return -1;
+ if (qemuProcessOpenVfioFds(vm) < 0)
+ return -1;
VIR_DEBUG("Preparing chr device backends");
if (qemuProcessPrepareHostBackendChardev(vm) < 0)
diff --git a/src/util/virpci.c b/src/util/virpci.c
index 90617e69c6..2348a98003 100644
--- a/src/util/virpci.c
+++ b/src/util/virpci.c
@@ -3320,3 +3320,42 @@ virPCIDeviceAddressFree(virPCIDeviceAddress *address)
{
g_free(address);
}
+
+/**
+ * virPCIDeviceGetVfioPath:
+ * @addr: host device PCI address
+ * @vfioPath: returned VFIO device path
+ *
+ * Constructs the VFIO device path for a PCI hostdev.
+ *
+ * Returns: 0 on success, -1 on failure
+ */
+int
+virPCIDeviceGetVfioPath(virPCIDeviceAddress *addr,
+ char **vfioPath)
+{
+ g_autofree char *addrStr = NULL;
+ g_autofree char *sysfsPath = NULL;
+ g_autoptr(DIR) dir = NULL;
+ struct dirent *entry = NULL;
+
+ *vfioPath = NULL;
+ addrStr = virPCIDeviceAddressAsString(addr);
+
+ /* Look in device's vfio-dev subdirectory */
+ sysfsPath = g_strdup_printf("/sys/bus/pci/devices/%s/vfio-dev/", addrStr);
+
+ if (virDirOpen(&dir, sysfsPath) == 1) {
+ while (virDirRead(dir, &entry, sysfsPath) > 0) {
+ if (STRPREFIX(entry->d_name, "vfio")) {
+ *vfioPath = g_strdup_printf("/dev/vfio/devices/%s", entry->d_name);
+ return 0;
+ }
+ }
+ }
+
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("cannot find VFIO device for PCI device %1$s"),
+ addrStr);
+ return -1;
+}
diff --git a/src/util/virpci.h b/src/util/virpci.h
index fc538566e1..24ede10755 100644
--- a/src/util/virpci.h
+++ b/src/util/virpci.h
@@ -296,6 +296,8 @@ void virPCIEDeviceInfoFree(virPCIEDeviceInfo *dev);
void virPCIDeviceAddressFree(virPCIDeviceAddress *address);
+int virPCIDeviceGetVfioPath(virPCIDeviceAddress *addr, char **vfioPath);
+
G_DEFINE_AUTOPTR_CLEANUP_FUNC(virPCIDevice, virPCIDeviceFree);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(virPCIDeviceAddress, virPCIDeviceAddressFree);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(virPCIEDeviceInfo, virPCIEDeviceInfoFree);
--
2.52.0

View File

@ -0,0 +1,175 @@
From a444918da5bd01fc11793c82ad33308892777c3a Mon Sep 17 00:00:00 2001
Message-ID: <a444918da5bd01fc11793c82ad33308892777c3a.1770383182.git.jdenemar@redhat.com>
From: Nathan Chen <nathanc@nvidia.com>
Date: Fri, 30 Jan 2026 10:59:16 -0800
Subject: [PATCH] qemu: open iommufd FD from libvirt backend
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Open iommufd FD from libvirt backend without exposing
these FDs to XML users, i.e. one per domain for
/dev/iommu, and pass the FD to qemu command line. Set
per-process memory accounting for iommufd instead of
the default per-user memory accounting.
Suggested-by: Ján Tomko <jtomko@redhat.com>
Signed-off-by: Nathan Chen <nathanc@nvidia.com>
Reviewed-by: Pavel Hrdina <phrdina@redhat.com>
(cherry picked from commit 2f0999a161910e3992458902ce90d37f8b8f2642)
Resolves: https://issues.redhat.com/browse/RHEL-74202
Resolves: https://issues.redhat.com/browse/RHEL-126346
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
---
src/qemu/qemu_command.c | 13 +++++++++++--
src/qemu/qemu_domain.c | 1 +
src/qemu/qemu_domain.h | 2 ++
src/qemu/qemu_process.c | 43 +++++++++++++++++++++++++++++++++++++++++
4 files changed, 57 insertions(+), 2 deletions(-)
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 83935e82c3..f355352018 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -5342,9 +5342,13 @@ qemuBuildHostdevCommandLine(virCommand *cmd,
static int
qemuBuildIOMMUFDCommandLine(virCommand *cmd,
- const virDomainDef *def)
+ const virDomainDef *def,
+ virDomainObj *vm)
{
size_t i;
+ qemuDomainObjPrivate *priv = vm->privateData;
+ g_autofree char *fdstr = g_strdup_printf("%d", priv->iommufd);
+
for (i = 0; i < def->nhostdevs; i++) {
virDomainHostdevDef *hostdev = def->hostdevs[i];
@@ -5363,8 +5367,13 @@ qemuBuildIOMMUFDCommandLine(virCommand *cmd,
if (subsys->u.pci.driver.iommufd != VIR_TRISTATE_BOOL_YES)
continue;
+ virCommandPassFD(cmd, priv->iommufd, VIR_COMMAND_PASS_FD_CLOSE_PARENT);
+
+ priv->iommufd = -1;
+
if (qemuMonitorCreateObjectProps(&props, "iommufd",
"iommufd0",
+ "S:fd", fdstr,
NULL) < 0)
return -1;
@@ -10990,7 +10999,7 @@ qemuBuildCommandLine(virDomainObj *vm,
if (qemuBuildRedirdevCommandLine(cmd, def, qemuCaps) < 0)
return NULL;
- if (qemuBuildIOMMUFDCommandLine(cmd, def) < 0)
+ if (qemuBuildIOMMUFDCommandLine(cmd, def, vm) < 0)
return NULL;
if (qemuBuildHostdevCommandLine(cmd, def, qemuCaps) < 0)
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 3366214677..8e1ebe7799 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -2042,6 +2042,7 @@ qemuDomainObjPrivateAlloc(void *opaque)
priv->blockjobs = virHashNew(virObjectUnref);
priv->fds = virHashNew(g_object_unref);
+ priv->iommufd = -1;
priv->pidMonitored = -1;
/* agent commands block by default, user can choose different behavior */
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
index 88c8416aa4..3361e97315 100644
--- a/src/qemu/qemu_domain.h
+++ b/src/qemu/qemu_domain.h
@@ -264,6 +264,8 @@ struct _qemuDomainObjPrivate {
/* named file descriptor groups associated with the VM */
GHashTable *fds;
+ int iommufd;
+
char *memoryBackingDir;
};
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 1ac57a6321..d8f0c78fd1 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -104,6 +104,7 @@
#include "backup_conf.h"
#include "storage_file_probe.h"
#include "virpci.h"
+#include "viriommufd.h"
#include "logging/log_manager.h"
#include "logging/log_protocol.h"
@@ -7672,6 +7673,42 @@ qemuProcessPrepareHostBackendChardevHotplug(virDomainObj *vm,
return 0;
}
+/**
+ * qemuProcessOpenIommuFd:
+ * @vm: domain object
+ * @iommuFd: returned file descriptor
+ *
+ * Opens /dev/iommu file descriptor for the VM.
+ *
+ * Returns: FD on success, -1 on failure
+ */
+static int
+qemuProcessOpenIommuFd(virDomainObj *vm)
+{
+ int fd = -1;
+
+ VIR_DEBUG("Opening IOMMU FD for domain %s", vm->def->name);
+
+ if ((fd = open(VIR_IOMMU_DEV_PATH, O_RDWR | O_CLOEXEC)) < 0) {
+ if (errno == ENOENT) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("IOMMU FD support requires /dev/iommu device"));
+ } else {
+ virReportSystemError(errno, "%s",
+ _("cannot open /dev/iommu"));
+ }
+ return -1;
+ }
+
+ if (virIOMMUFDSetRLimitMode(fd, true) < 0) {
+ VIR_FORCE_CLOSE(fd);
+ return -1;
+ }
+
+ VIR_DEBUG("Opened IOMMU FD %d for domain %s", fd, vm->def->name);
+ return fd;
+}
+
/**
* qemuProcessOpenVfioDeviceFd:
* @hostdev: host device definition
@@ -7726,6 +7763,7 @@ qemuProcessOpenVfioDeviceFd(virDomainHostdevDef *hostdev)
static int
qemuProcessOpenVfioFds(virDomainObj *vm)
{
+ qemuDomainObjPrivate *priv = vm->privateData;
size_t i;
/* Check if we have any hostdevs that need VFIO FDs */
@@ -7741,6 +7779,11 @@ qemuProcessOpenVfioFds(virDomainObj *vm)
hostdevPriv->vfioDeviceFd = qemuProcessOpenVfioDeviceFd(hostdev);
if (hostdevPriv->vfioDeviceFd == -1)
return -1;
+
+ /* Open IOMMU FD */
+ priv->iommufd = qemuProcessOpenIommuFd(vm);
+ if (priv->iommufd == -1)
+ return -1;
}
}
--
2.52.0

View File

@ -0,0 +1,62 @@
From 0359b5fcf870f955bbdca998e5a02261e27c40b7 Mon Sep 17 00:00:00 2001
Message-ID: <0359b5fcf870f955bbdca998e5a02261e27c40b7.1771336681.git.jdenemar@redhat.com>
From: Peter Krempa <pkrempa@redhat.com>
Date: Thu, 29 Jan 2026 11:21:38 +0100
Subject: [PATCH] qemu: process: Rename 'qemuProcessSetupDiskThrottling' to
'qemuProcessSetupDisks'
Rename the runtime disk option setup function to be universal.
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit 42a39d703d98e4e48f0f9c8779884b6ac107de26)
https://issues.redhat.com/browse/RHEL-147866 [rhel-9.8]
https://issues.redhat.com/browse/RHEL-131335 [rhel-10.2]
---
src/qemu/qemu_process.c | 16 +++++++---------
1 file changed, 7 insertions(+), 9 deletions(-)
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index c99bb36c93..aadfaa92b0 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -7964,21 +7964,19 @@ qemuProcessSetupDiskPropsRuntime(qemuMonitor *mon,
/**
- * qemuProcessSetupDiskThrottling:
+ * qemuProcessSetupDisks:
*
- * Sets up disk trottling for -blockdev via block_set_io_throttle monitor
- * command. This hack should be replaced by proper use of the 'throttle'
- * blockdev driver in qemu once it will support changing of the throttle group.
- * Same hack is done in qemuDomainAttachDiskGeneric.
+ * Sets up disk settings available only at runtime:
+ * - trottling for -blockdev via block_set_io_throttle QMP command
*/
static int
-qemuProcessSetupDiskThrottling(virDomainObj *vm,
- virDomainAsyncJob asyncJob)
+qemuProcessSetupDisks(virDomainObj *vm,
+ virDomainAsyncJob asyncJob)
{
size_t i;
int ret = -1;
- VIR_DEBUG("Setting up disk throttling for -blockdev via block_set_io_throttle");
+ VIR_DEBUG("Setting up disk config via runtime commands");
if (qemuDomainObjEnterMonitorAsync(vm, asyncJob) < 0)
return -1;
@@ -8575,7 +8573,7 @@ qemuProcessLaunch(virConnectPtr conn,
if (qemuProcessSetupBalloon(vm, asyncJob) < 0)
goto cleanup;
- if (qemuProcessSetupDiskThrottling(vm, asyncJob) < 0)
+ if (qemuProcessSetupDisks(vm, asyncJob) < 0)
goto cleanup;
/* Since CPUs were not started yet, the balloon could not return the memory
--
2.53.0

View File

@ -0,0 +1,119 @@
From 8e9dc8aed52c98c3683949dfe1127061bd9df47a Mon Sep 17 00:00:00 2001
Message-ID: <8e9dc8aed52c98c3683949dfe1127061bd9df47a.1766070439.git.jdenemar@redhat.com>
From: Peter Krempa <pkrempa@redhat.com>
Date: Mon, 1 Dec 2025 11:35:32 +0100
Subject: [PATCH] qemu: tpm: Account for possible migration without actually
sharing storage
The current logic in 'qemuTPMEmulatorBuildCommand' skips all setup if
the *location* of the data is on what we'd consider shared storage.
This means that if the location is not actually shared (e.g. it's shared
betweeh some other hosts than the two doing the migration) and the path
wasn't ever used (e.g. by migrating out) from the host where we're
migrating into the complete setup of the location would be skipped even
when it doesn't exist.
Fix the logic by skipping only some of the setup steps so that
'qemuTPMEmulatorCreateStorage' can still create the storage if it
doesn't exist.
The rest of the code then needs to take the 'created' flag returned from
'qemuTPMEmulatorCreateStorage' into account.
Fixes: 68103e9daf633b789428fedef56f816c92f6ee75
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit d56d0560946770d4364a4918cc289e6a7fe5d15c)
https://issues.redhat.com/browse/RHEL-132534
---
src/qemu/qemu_tpm.c | 29 ++++++++++++++++++++---------
1 file changed, 20 insertions(+), 9 deletions(-)
diff --git a/src/qemu/qemu_tpm.c b/src/qemu/qemu_tpm.c
index 4c9445d72c..660410bcba 100644
--- a/src/qemu/qemu_tpm.c
+++ b/src/qemu/qemu_tpm.c
@@ -158,6 +158,7 @@ qemuTPMEmulatorGetPid(const char *swtpmStateDir,
/**
* qemuTPMEmulatorCreateStorage:
* @tpm: TPM definition for an emulator type
+ * @sharedStorageMigration: VM is being migrated with possibly shared storage
* @created: a pointer to a bool that will be set to true if the
* storage was created because it did not exist yet
* @swtpm_user: The uid that needs to be able to access the directory
@@ -169,6 +170,7 @@ qemuTPMEmulatorGetPid(const char *swtpmStateDir,
*/
static int
qemuTPMEmulatorCreateStorage(virDomainTPMDef *tpm,
+ bool sharedStorageMigration,
bool *created,
uid_t swtpm_user,
gid_t swtpm_group)
@@ -187,8 +189,17 @@ qemuTPMEmulatorCreateStorage(virDomainTPMDef *tpm,
*created = false;
if (!virFileExists(source_path) ||
- virDirIsEmpty(source_path, true) > 0)
+ virDirIsEmpty(source_path, true) > 0) {
*created = true;
+ } else {
+ /* If the location exists and is shared, we don't need to create it
+ * during migration */
+ if (sharedStorageMigration) {
+ VIR_DEBUG("Skipping TPM storage creation. Path '%s' already exists and is on shared storage.",
+ source_path);
+ return 0;
+ }
+ }
if (virDirCreate(source_path, 0700, swtpm_user, swtpm_group,
VIR_DIR_CREATE_ALLOW_EXIST) < 0) {
@@ -809,16 +820,13 @@ qemuTPMEmulatorBuildCommand(virDomainTPMDef *tpm,
run_setup = true;
}
- /* Do not create storage and run swtpm_setup on incoming migration over
- * shared storage
- */
on_shared_storage = virFileIsSharedFS(tpm->data.emulator.source_path,
cfg->sharedFilesystems) == 1;
- if (incomingMigration && on_shared_storage)
- create_storage = false;
if (create_storage) {
- if (qemuTPMEmulatorCreateStorage(tpm, &created,
+ if (qemuTPMEmulatorCreateStorage(tpm,
+ incomingMigration && on_shared_storage,
+ &created,
cfg->swtpm_user, cfg->swtpm_group) < 0)
return NULL;
run_setup = created;
@@ -885,6 +893,9 @@ qemuTPMEmulatorBuildCommand(virDomainTPMDef *tpm,
/* If swtpm supports it and the TPM state is stored on shared storage,
* start swtpm with --migration release-lock-outgoing so it can migrate
* across shared storage if needed.
+ *
+ * Note that if 'created' is true, the location didn't exist so the storage
+ * is not actually shared.
*/
QEMU_DOMAIN_TPM_PRIVATE(tpm)->swtpm.can_migrate_shared_storage = false;
if (on_shared_storage &&
@@ -892,13 +903,13 @@ qemuTPMEmulatorBuildCommand(virDomainTPMDef *tpm,
virCommandAddArg(cmd, "--migration");
virCommandAddArgFormat(cmd, "release-lock-outgoing%s",
- incomingMigration ? ",incoming": "");
+ incomingMigration && !created ? ",incoming": "");
QEMU_DOMAIN_TPM_PRIVATE(tpm)->swtpm.can_migrate_shared_storage = true;
} else {
/* Report an error if there's an incoming migration across shared
* storage and swtpm does not support the --migration option.
*/
- if (incomingMigration && on_shared_storage) {
+ if (incomingMigration && on_shared_storage && !created) {
virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED,
_("%1$s (on destination side) does not support the --migration option needed for migration with shared storage"),
swtpm);
--
2.52.0

View File

@ -1,49 +0,0 @@
From d7285cb688e4f6b61dd842be7d0a2e773ad7d21b Mon Sep 17 00:00:00 2001
Message-ID: <d7285cb688e4f6b61dd842be7d0a2e773ad7d21b.1723213495.git.jdenemar@redhat.com>
From: =?UTF-8?q?J=C3=A1n=20Tomko?= <jtomko@redhat.com>
Date: Tue, 23 Jul 2024 14:14:13 +0200
Subject: [PATCH] qemu: virtiofs: cache: use 'never' instead of 'none'
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The new option style renamed one of the cache modes.
https://issues.redhat.com/browse/RHEL-50329
Signed-off-by: Ján Tomko <jtomko@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit 8d3b2397372111d15d6b79138c5c5a80203f85f5)
Signed-off-by: Ján Tomko <jtomko@redhat.com>
---
src/qemu/qemu_virtiofs.c | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/src/qemu/qemu_virtiofs.c b/src/qemu/qemu_virtiofs.c
index 0e3c7dbb58..c7be2766a2 100644
--- a/src/qemu/qemu_virtiofs.c
+++ b/src/qemu/qemu_virtiofs.c
@@ -147,10 +147,20 @@ qemuVirtioFSBuildCommandLine(virQEMUDriverConfig *cfg,
virCommandAddArg(cmd, "--shared-dir");
virCommandAddArg(cmd, fs->src->path);
- if (fs->cache) {
+ switch (fs->cache) {
+ case VIR_DOMAIN_FS_CACHE_MODE_DEFAULT:
+ case VIR_DOMAIN_FS_CACHE_MODE_LAST:
+ break;
+ case VIR_DOMAIN_FS_CACHE_MODE_NONE:
+ virCommandAddArg(cmd, "--cache");
+ virCommandAddArg(cmd, "never");
+ break;
+ case VIR_DOMAIN_FS_CACHE_MODE_ALWAYS:
virCommandAddArg(cmd, "--cache");
virCommandAddArg(cmd, virDomainFSCacheModeTypeToString(fs->cache));
+ break;
}
+
if (fs->sandbox) {
virCommandAddArg(cmd, "--sandbox");
virCommandAddArg(cmd, virDomainFSSandboxModeTypeToString(fs->sandbox));
--
2.46.0

View File

@ -0,0 +1,68 @@
From 2f60aff267af628839c90fe36cacbc9d5057509a Mon Sep 17 00:00:00 2001
Message-ID: <2f60aff267af628839c90fe36cacbc9d5057509a.1769699749.git.jdenemar@redhat.com>
From: Peter Krempa <pkrempa@redhat.com>
Date: Fri, 16 Jan 2026 16:38:38 +0100
Subject: [PATCH] qemuDomainSetBlockIoTuneField: Move setting of 'group_name'
out of the loop
The refactor will simplify further change which will introduce another
source for the group name.
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit fa064375668df0e67b4d68fdfc4a386862026f3f)
https://issues.redhat.com/browse/RHEL-141820 [rhel-10.2]
https://issues.redhat.com/browse/RHEL-144010 [rhel-9.8]
---
src/qemu/qemu_driver.c | 20 ++++++++++++--------
1 file changed, 12 insertions(+), 8 deletions(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 194017a29a..ecfb65c535 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -15173,6 +15173,7 @@ qemuDomainSetBlockIoTuneFields(virDomainBlockIoTuneInfo *info,
int *eventNparams,
int *eventMaxparams)
{
+ const char *param_group_name = NULL;
size_t i;
#define SET_IOTUNE_FIELD(FIELD, BOOL, CONST) \
@@ -15218,15 +15219,8 @@ qemuDomainSetBlockIoTuneFields(virDomainBlockIoTuneInfo *info,
WRITE_IOPS_SEC_MAX);
SET_IOTUNE_FIELD(size_iops_sec, SIZE_IOPS, SIZE_IOPS_SEC);
- /* NB: Cannot use macro since this is a value.s not a value.ul */
if (STREQ(param->field, VIR_DOMAIN_BLOCK_IOTUNE_GROUP_NAME)) {
- info->group_name = g_strdup(param->value.s);
- *set_fields |= QEMU_BLOCK_IOTUNE_SET_GROUP_NAME;
- if (virTypedParamsAddString(eventParams, eventNparams,
- eventMaxparams,
- VIR_DOMAIN_TUNABLE_BLKDEV_GROUP_NAME,
- param->value.s) < 0)
- return -1;
+ param_group_name = param->value.s;
continue;
}
@@ -15244,6 +15238,16 @@ qemuDomainSetBlockIoTuneFields(virDomainBlockIoTuneInfo *info,
WRITE_IOPS_SEC_MAX_LENGTH);
}
+ if (param_group_name) {
+ info->group_name = g_strdup(param_group_name);
+ *set_fields |= QEMU_BLOCK_IOTUNE_SET_GROUP_NAME;
+ if (virTypedParamsAddString(eventParams, eventNparams,
+ eventMaxparams,
+ VIR_DOMAIN_TUNABLE_BLKDEV_GROUP_NAME,
+ param_group_name) < 0)
+ return -1;
+ }
+
#undef SET_IOTUNE_FIELD
return 0;
--
2.52.0

View File

@ -0,0 +1,75 @@
From f44d3fa49e7f1507e93c1e9525dd0db4227809cc Mon Sep 17 00:00:00 2001
Message-ID: <f44d3fa49e7f1507e93c1e9525dd0db4227809cc.1769699749.git.jdenemar@redhat.com>
From: Peter Krempa <pkrempa@redhat.com>
Date: Fri, 16 Jan 2026 16:39:40 +0100
Subject: [PATCH] qemuDomainSetThrottleGroup: Always honour thottle group name
passed as argument
Due to the code share with 'qemuDomainSetBlockIoTune' the throttle group
setting code accepts the throttle group name also via typed parameters.
In 'qemuDomainSetThrottleGroup', this means that there are 2 ways to
pass it the throttle group name and both are handled slightly
differently. Specifically the name of the group used in the list of
groups is the name taken from the typed parameters rather than the one
passed via API. We also don't validate that they match.
Now if the name in the typed parameters is missing we'd add empty string
to the group list which would later crash when looking up the group
name.
To avoid this problem always use the name passed via argument. This is
achieved by passing it into 'qemuDomainSetBlockIoTuneFields' so that it
overrides whatever is in the typed parameters.
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit 0cd13906dcf15ea5709a7b253466816a1b875640)
https://issues.redhat.com/browse/RHEL-141820 [rhel-10.2]
https://issues.redhat.com/browse/RHEL-144010 [rhel-9.8]
---
src/qemu/qemu_driver.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index ecfb65c535..a6d5dd6e05 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -15168,6 +15168,7 @@ static int
qemuDomainSetBlockIoTuneFields(virDomainBlockIoTuneInfo *info,
virTypedParameterPtr params,
int nparams,
+ const char *group_name,
qemuBlockIoTuneSetFlags *set_fields,
virTypedParameterPtr *eventParams,
int *eventNparams,
@@ -15238,6 +15239,10 @@ qemuDomainSetBlockIoTuneFields(virDomainBlockIoTuneInfo *info,
WRITE_IOPS_SEC_MAX_LENGTH);
}
+ /* The name of the throttle group passed via API always takes precedence */
+ if (group_name)
+ param_group_name = group_name;
+
if (param_group_name) {
info->group_name = g_strdup(param_group_name);
*set_fields |= QEMU_BLOCK_IOTUNE_SET_GROUP_NAME;
@@ -15385,6 +15390,7 @@ qemuDomainSetBlockIoTune(virDomainPtr dom,
if (qemuDomainSetBlockIoTuneFields(&info,
params,
nparams,
+ NULL,
&set_fields,
&eventParams,
&eventNparams,
@@ -20379,6 +20385,7 @@ qemuDomainSetThrottleGroup(virDomainPtr dom,
if (qemuDomainSetBlockIoTuneFields(&info,
params,
nparams,
+ groupname,
&set_fields,
&eventParams,
&eventNparams,
--
2.52.0

View File

@ -0,0 +1,43 @@
From e48225074a9179e73b8ce9a573a513e619ae0a65 Mon Sep 17 00:00:00 2001
Message-ID: <e48225074a9179e73b8ce9a573a513e619ae0a65.1769699749.git.jdenemar@redhat.com>
From: Peter Krempa <pkrempa@redhat.com>
Date: Fri, 16 Jan 2026 16:39:49 +0100
Subject: [PATCH] qemuDomainSetThrottleGroup: Don't put group name into the
'tunable' event twice
'qemuDomainSetBlockIoTuneFields' already populates the contents of the
VIR_DOMAIN_EVENT_ID_TUNABLE params with the group name so there's no
need to do it explicitly. We'd report the group name twice:
event 'tunable' for domain 'cd':
blkdeviotune.group_name: asdf
blkdeviotune.total_bytes_sec: 1234
blkdeviotune.group_name: asdf
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit adcc14e1538433ec1b2f4b103cdf641917e63242)
https://issues.redhat.com/browse/RHEL-141820 [rhel-10.2]
https://issues.redhat.com/browse/RHEL-144010 [rhel-9.8]
---
src/qemu/qemu_driver.c | 4 ----
1 file changed, 4 deletions(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index a6d5dd6e05..08a547c546 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -20378,10 +20378,6 @@ qemuDomainSetThrottleGroup(virDomainPtr dom,
if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0)
goto endjob;
- if (virTypedParamsAddString(&eventParams, &eventNparams, &eventMaxparams,
- VIR_DOMAIN_TUNABLE_BLKDEV_GROUP_NAME, groupname) < 0)
- goto endjob;
-
if (qemuDomainSetBlockIoTuneFields(&info,
params,
nparams,
--
2.52.0

View File

@ -0,0 +1,38 @@
From fee37458a1f93dc30a209ceeda1ec31847884fcf Mon Sep 17 00:00:00 2001
Message-ID: <fee37458a1f93dc30a209ceeda1ec31847884fcf.1769699749.git.jdenemar@redhat.com>
From: Peter Krempa <pkrempa@redhat.com>
Date: Fri, 16 Jan 2026 16:36:50 +0100
Subject: [PATCH] qemuDomainSetThrottleGroup: Enforce non-zero 'groupname'
string length
Having a name of 0 characters makes no sense. Reject it.
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit abcdc9511b1c78df7dcdee9f01c6d55651d3a424)
https://issues.redhat.com/browse/RHEL-141820 [rhel-10.2]
https://issues.redhat.com/browse/RHEL-144010 [rhel-9.8]
---
src/qemu/qemu_driver.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index f2e024dae3..194017a29a 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -20345,6 +20345,12 @@ qemuDomainSetThrottleGroup(virDomainPtr dom,
virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
VIR_DOMAIN_AFFECT_CONFIG, -1);
+ if (strlen(groupname) == 0) {
+ virReportError(VIR_ERR_INVALID_ARG, "%s",
+ _("'groupname' parameter string must have non-zero length"));
+ return -1;
+ }
+
if (qemuDomainValidateBlockIoTune(params, nparams) < 0)
return -1;
--
2.52.0

View File

@ -0,0 +1,98 @@
From bbd0fde5f840726928cdcd06691da13f1093c02e Mon Sep 17 00:00:00 2001
Message-ID: <bbd0fde5f840726928cdcd06691da13f1093c02e.1770203422.git.jdenemar@redhat.com>
From: Peter Krempa <pkrempa@redhat.com>
Date: Tue, 27 Jan 2026 17:28:48 +0100
Subject: [PATCH] qemuMigrationDstPrepareAnyBlockDirtyBitmaps: Always consider
offered bitmaps
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Consider bitmaps for incoming migration regardless of non-shared storage
flag.
When bitmaps are offered from the source, consult the local image if the
bitmap is present and if not accept migration. Migration of bitmaps
which exist in the qcow2 metadata is skipped because qemu rejects such
setup (although handles it correctly in case of shared storage setup;
see below).
This allows bitmap propagation for cases when the qcow2 image is not
actually shared between destinations but the data is (using the
data_file feature).
At the same time this preserves existing bitmap handling semantics for
other cases. Specifically qemu, in case of shared storage properly
propagates the bitmap which was already recorded in the qcow2 metadata
on disk even if libvirt doesn't instruct migration, yet tolerates
migration instruction if the file is not yet recorded in the on-disk
metadata. In both cases the contents are preserved correctly.
When storage is not shared (which includes even cases when we migrate
it via NBD) it's expected that the bitmaps don't exist on the
destination and thus all will be picked for migration. We can also
infer that this wasn't ever a problem by the fact that the code skipping
migration of existing bitmaps was broken until recently, and qemu
would refuse such config.
I've tested all the above scenarios including verifying that the
resulting bitmaps capture dirtied regions before and after migration.
For testing this the following command is useful:
virsh qemu-monitor-command --domain DOMNAME --hmp 'qemu-io -d /machine/peripheral/virtio-disk0/virtio-backend "write -P 0xcc 4M 1M"'
Which simulates a write from the guest side without the need to interact
with the guest OS.
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
(cherry picked from commit bf34b90bb4e39b3a2fd22a5531f5ea5a95681015)
https://issues.redhat.com/browse/RHEL-145769 [rhel-10.2]
https://issues.redhat.com/browse/RHEL-145770 [rhel-9.8]
---
src/qemu/qemu_migration.c | 10 +++-------
1 file changed, 3 insertions(+), 7 deletions(-)
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index 755b9a5e1a..2a4df1191d 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -3183,7 +3183,6 @@ qemuMigrationDstPrepare(virQEMUDriver *driver,
* @vm: domain object
* @mig: migration cookie
* @migParams: migration parameters
- * @flags: migration flags
*
* Checks whether block dirty bitmaps offered by the migration source are
* to be migrated (e.g. they don't exist, the destination is compatible etc)
@@ -3194,16 +3193,13 @@ qemuMigrationDstPrepare(virQEMUDriver *driver,
static int
qemuMigrationDstPrepareAnyBlockDirtyBitmaps(virDomainObj *vm,
qemuMigrationCookie *mig,
- qemuMigrationParams *migParams,
- unsigned int flags)
+ qemuMigrationParams *migParams)
{
g_autoptr(virJSONValue) mapping = NULL;
g_autoptr(GHashTable) blockNamedNodeData = NULL;
GSList *nextdisk;
- if (!mig->nbd ||
- !mig->blockDirtyBitmaps ||
- !(flags & (VIR_MIGRATE_NON_SHARED_DISK | VIR_MIGRATE_NON_SHARED_INC)))
+ if (!mig->blockDirtyBitmaps)
return 0;
if (qemuMigrationCookieBlockDirtyBitmapsMatchDisks(vm->def, mig->blockDirtyBitmaps) < 0)
@@ -3350,7 +3346,7 @@ qemuMigrationDstPrepareActive(virQEMUDriver *driver,
goto error;
}
- if (qemuMigrationDstPrepareAnyBlockDirtyBitmaps(vm, mig, migParams, flags) < 0)
+ if (qemuMigrationDstPrepareAnyBlockDirtyBitmaps(vm, mig, migParams) < 0)
goto error;
if (qemuMigrationParamsCheck(vm, VIR_ASYNC_JOB_MIGRATION_IN, migParams,
--
2.52.0

View File

@ -0,0 +1,68 @@
From b99fb51812da73df754151c59c259d15fa654168 Mon Sep 17 00:00:00 2001
Message-ID: <b99fb51812da73df754151c59c259d15fa654168.1770203422.git.jdenemar@redhat.com>
From: Peter Krempa <pkrempa@redhat.com>
Date: Tue, 27 Jan 2026 19:22:08 +0100
Subject: [PATCH] qemuMigrationDstPrepareAnyBlockDirtyBitmaps: Fix check for
existing bitmaps
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
On incoming migration qemu doesn't load bitmaps into memory (which makes
them available under the 'dirty-bitmaps' field which we parse as the
'bitmaps' array in 'qemuBlockNamedNodeData') until after actually
resuming CPUs, thus the check for existing bitmaps never actually
worked.
We need to check the 'qcow2bitmaps' field instead which is populated
from the qcow2 headers prior to activating the image.
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
(cherry picked from commit 0c75fc1747f039bf878ceab69cf12482ebb14095)
https://issues.redhat.com/browse/RHEL-145769 [rhel-10.2]
https://issues.redhat.com/browse/RHEL-145770 [rhel-9.8]
---
src/qemu/qemu_migration.c | 16 +++++++---------
1 file changed, 7 insertions(+), 9 deletions(-)
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index 9059f9aa3a..723e131c98 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -3227,6 +3227,8 @@ qemuMigrationDstPrepareAnyBlockDirtyBitmaps(virDomainObj *vm,
qemuBlockNamedNodeData *nodedata;
GSList *nextbitmap;
+ VIR_DEBUG("offer migrate bitmaps for '%s'", disk->target);
+
if (!(nodedata = virHashLookup(blockNamedNodeData, disk->nodename))) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("failed to find data for block node '%1$s'"),
@@ -3243,18 +3245,14 @@ qemuMigrationDstPrepareAnyBlockDirtyBitmaps(virDomainObj *vm,
for (nextbitmap = disk->bitmaps; nextbitmap; nextbitmap = nextbitmap->next) {
qemuMigrationBlockDirtyBitmapsDiskBitmap *bitmap = nextbitmap->data;
- size_t k;
/* don't migrate into existing bitmaps */
- for (k = 0; k < nodedata->nbitmaps; k++) {
- if (STREQ(bitmap->bitmapname, nodedata->bitmaps[k]->name)) {
- bitmap->skip = true;
- break;
- }
- }
+ if (nodedata->qcow2bitmaps)
+ bitmap->skip = g_strv_contains((const char **) nodedata->qcow2bitmaps, bitmap->bitmapname);
+
+ VIR_DEBUG("offer migrate bitmap '%s' disk '%s' -> skip: '%d'",
+ bitmap->bitmapname, disk->target, bitmap->skip);
- if (bitmap->skip)
- continue;
}
}
--
2.52.0

View File

@ -0,0 +1,56 @@
From 5a7cc07af8355ae117d04d357bd8b694fc2af091 Mon Sep 17 00:00:00 2001
Message-ID: <5a7cc07af8355ae117d04d357bd8b694fc2af091.1769173967.git.jdenemar@redhat.com>
From: Peter Krempa <pkrempa@redhat.com>
Date: Mon, 12 Jan 2026 10:54:38 +0100
Subject: [PATCH] qemuSecurityMoveImageMetadata: Move seclabels only to
virStorageSource of same type
The concept of moving a seclabel is used e.g. when a new image is
introduced to the backing chain (or one of the existing ones becomes
active during block commit). What it does is that it moves the metedata
remembering the original seclabel to the new image.
That idea works reasonably well if both the original and new image are
of same type e.g. a file, where they have comparable seclabel.
It breaks down though when you e.g. create a snapshot stored in a 'file'
on top of a disk originally backed by a 'block' storage source, since
the seclabels differ quite siginificantly.
This patch restricts the seclabel move in qemuSecurityMoveImageMetadata
to happen only if the storage sources are of same type to avoid the
issue. This means that the seclabels will not be remebered and will be
restored to the default but it's better than to transfer wrong labels.
Resolves: https://issues.redhat.com/browse/RHEL-114412
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit 37d51c0d27692a245d7a5eeeef57748e7574de4b)
---
src/qemu/qemu_security.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/src/qemu/qemu_security.c b/src/qemu/qemu_security.c
index 6bb0f9170d..84cb981a96 100644
--- a/src/qemu/qemu_security.c
+++ b/src/qemu/qemu_security.c
@@ -201,6 +201,16 @@ qemuSecurityMoveImageMetadata(virQEMUDriver *driver,
if (qemuDomainNamespaceEnabled(vm, QEMU_DOMAIN_NS_MOUNT))
pid = vm->pid;
+ /* Moving seclabel metadata makes sense only when 'src' and 'dst' are of
+ * the same type. Otherwise 'dst' could end up with a seclabel that doesn't
+ * make sense for it (e.g. a seclabel originating from a block device /dev
+ * node moved to a file), once the seclabels are restored for it */
+ if (src && dst && src->type != dst->type) {
+ VIR_DEBUG("dropping security label metadata instead of moving it from '%s' to '%s' due to type mismatch",
+ NULLSTR(src->path), NULLSTR(dst->path));
+ dst = NULL;
+ }
+
return virSecurityManagerMoveImageMetadata(driver->securityManager,
cfg->sharedFilesystems,
pid, src, dst);
--
2.52.0

View File

@ -0,0 +1,48 @@
From 744a5361793546bed7976acebed669b1928e8c9d Mon Sep 17 00:00:00 2001
Message-ID: <744a5361793546bed7976acebed669b1928e8c9d.1769699749.git.jdenemar@redhat.com>
From: Peter Krempa <pkrempa@redhat.com>
Date: Fri, 23 Jan 2026 08:42:50 +0100
Subject: [PATCH] qemuSnapshotDiskHasBackingDisk: Avoid call of
virStorageSourceIsSameLocation with NULL argument
When the 'backingStore' pointer is not populated the function calls
'virStorageSourceGetMetadata' to try to populate it but if the on-disk
metadata doesn't have a backing image (e.g. if it's the 'base' image of
the chain) the 'backingStore' or the metadata fetcher fails the pointer
will still be NULL.
The function then calls 'virStorageSourceIsSameLocation' but the
internal functions for dealing with storage sources don't handle NULL
gracefully.
Since the code calling 'qemu-img' based on the data detected here
doesn't actually raise errors if the operations fail there's no point
in raising errors here either.
Closes: https://gitlab.com/libvirt/libvirt/-/issues/844
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Pavel Hrdina <phrdina@redhat.com>
(cherry picked from commit b43aee9cc904961e0f18156c3c84a3e460bdb7be)
https://issues.redhat.com/browse/RHEL-144089 [rhel-10.2]
https://issues.redhat.com/browse/RHEL-144090 [rhel-9.8]
---
src/qemu/qemu_snapshot.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/qemu/qemu_snapshot.c b/src/qemu/qemu_snapshot.c
index 302775af92..dfc3f449e3 100644
--- a/src/qemu/qemu_snapshot.c
+++ b/src/qemu/qemu_snapshot.c
@@ -3135,7 +3135,8 @@ qemuSnapshotDiskHasBackingDisk(void *payload,
if (!disk->src->backingStore)
ignore_value(virStorageSourceGetMetadata(disk->src, uid, gid, 1, false));
- if (virStorageSourceIsSameLocation(disk->src->backingStore, iterdata->diskSrc)) {
+ if (disk->src->backingStore &&
+ virStorageSourceIsSameLocation(disk->src->backingStore, iterdata->diskSrc)) {
struct _qemuSnapshotDisksWithBackingStoreData *data =
g_new0(struct _qemuSnapshotDisksWithBackingStoreData, 1);
--
2.52.0

View File

@ -0,0 +1,75 @@
From 78e9a796a24c4f60c162ee3643c4a251c97ab1d2 Mon Sep 17 00:00:00 2001
Message-ID: <78e9a796a24c4f60c162ee3643c4a251c97ab1d2.1769699749.git.jdenemar@redhat.com>
From: Peter Krempa <pkrempa@redhat.com>
Date: Mon, 26 Jan 2026 16:39:24 +0100
Subject: [PATCH] qemuSnapshotDiskHasBackingDisk: Use proper 'max_depth' when
calling 'virStorageSourceGetMetadata'
The 'max_depth' argument of 'virStorageSourceGetMetadata' doesn't just
limit how far the function goes but also fails completely if the chain
is deeper than the passed value.
In 'qemuSnapshotDiskHasBackingDisk' we only care about finding the
backing image, so just one level below, the passed path, but due to the
above setting '1' as max_depth will make the function simply fail every
time.
Extract and reuse QEMU_DOMAIN_STORAGE_SOURCE_CHAIN_MAX_DEPTH as the
detection depth. While '200' layers is overkill for this code, we also
start a full qemu instance just to delete an snapshot so this doens't
matter and still protects from self-referential images.
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Pavel Hrdina <phrdina@redhat.com>
(cherry picked from commit 6bcdf4ee59595041c76ed2339c45503723400737)
https://issues.redhat.com/browse/RHEL-144089 [rhel-10.2]
https://issues.redhat.com/browse/RHEL-144090 [rhel-9.8]
---
src/qemu/qemu_domain.c | 2 --
src/qemu/qemu_domain.h | 1 +
src/qemu/qemu_snapshot.c | 4 +++-
3 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index ac56fc7cb4..486a0e7913 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -6297,8 +6297,6 @@ qemuDomainStorageAlias(const char *device, int depth)
}
-#define QEMU_DOMAIN_STORAGE_SOURCE_CHAIN_MAX_DEPTH 200
-
/**
* qemuDomainStorageSourceValidateDepth:
* @src: storage source chain to validate
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
index 3396f929fd..b9bb338682 100644
--- a/src/qemu/qemu_domain.h
+++ b/src/qemu/qemu_domain.h
@@ -706,6 +706,7 @@ int qemuDomainCheckDiskStartupPolicy(virQEMUDriver *driver,
size_t diskIndex,
bool cold_boot);
+#define QEMU_DOMAIN_STORAGE_SOURCE_CHAIN_MAX_DEPTH 200
int qemuDomainStorageSourceValidateDepth(virStorageSource *src,
int add,
const char *diskdst);
diff --git a/src/qemu/qemu_snapshot.c b/src/qemu/qemu_snapshot.c
index 942ba0d437..c23add5103 100644
--- a/src/qemu/qemu_snapshot.c
+++ b/src/qemu/qemu_snapshot.c
@@ -3133,7 +3133,9 @@ qemuSnapshotDiskHasBackingDisk(void *payload,
NULL, &uid, &gid);
if (!disk->src->backingStore)
- ignore_value(virStorageSourceGetMetadata(disk->src, uid, gid, 1, false));
+ ignore_value(virStorageSourceGetMetadata(disk->src, uid, gid,
+ QEMU_DOMAIN_STORAGE_SOURCE_CHAIN_MAX_DEPTH,
+ false));
if (disk->src->backingStore &&
virStorageSourceIsSameLocation(disk->src->backingStore, iterdata->diskSrc)) {
--
2.52.0

View File

@ -0,0 +1,34 @@
From ca8a9f6b124dbfe5809c83d7f2d268bb18b9fa75 Mon Sep 17 00:00:00 2001
Message-ID: <ca8a9f6b124dbfe5809c83d7f2d268bb18b9fa75.1769699749.git.jdenemar@redhat.com>
From: Peter Krempa <pkrempa@redhat.com>
Date: Fri, 23 Jan 2026 08:54:32 +0100
Subject: [PATCH] qemuSnapshotUpdateBackingStore: Remove stale comment
The code does a 'qemu-img rebase' rather than a 'qemu-img create' what
the commit suggests. Since we enumerate all arguments right below,
there's no need for a comment.
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Pavel Hrdina <phrdina@redhat.com>
(cherry picked from commit 452c281aee7a043b59a288de043ea4e3b75a6b7c)
https://issues.redhat.com/browse/RHEL-144089 [rhel-10.2]
https://issues.redhat.com/browse/RHEL-144090 [rhel-9.8]
---
src/qemu/qemu_snapshot.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/src/qemu/qemu_snapshot.c b/src/qemu/qemu_snapshot.c
index dfc3f449e3..942ba0d437 100644
--- a/src/qemu/qemu_snapshot.c
+++ b/src/qemu/qemu_snapshot.c
@@ -3698,7 +3698,6 @@ qemuSnapshotUpdateBackingStore(qemuSnapshotDeleteExternalData *data)
struct _qemuSnapshotDisksWithBackingStoreData *backingData = cur->data;
g_autoptr(virCommand) cmd = NULL;
- /* creates cmd line args: qemu-img create -f qcow2 -o */
if (!(cmd = virCommandNewArgList("qemu-img",
"rebase",
"-u",
--
2.52.0

View File

@ -0,0 +1,97 @@
From 7d39e57db8479f4c481636c8c41311f3eabc935f Mon Sep 17 00:00:00 2001
Message-ID: <7d39e57db8479f4c481636c8c41311f3eabc935f.1769699749.git.jdenemar@redhat.com>
From: Peter Krempa <pkrempa@redhat.com>
Date: Mon, 26 Jan 2026 16:49:50 +0100
Subject: [PATCH] qemuSnapshotUpdateBackingStore: Retry as curent user if
qemu-img fails
The code calls 'qemu-img rebase' to fix the backing store references.
The 'qemu-img' process here is run as the 'qemu' user or whatever the
defaults and domain XML resolve to. Since this, in certain cases, works
also on images which are not part of the backing chain and in privileged
deployments thus can be owned by 'root:root' the update may fail
(silently).
To preserver root-squash deployments but fix also the above case, retry
the operation on failure as current user.
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Pavel Hrdina <phrdina@redhat.com>
(cherry picked from commit 6bb982178b40768f37c5177f317e73562733530f)
https://issues.redhat.com/browse/RHEL-144089 [rhel-10.2]
https://issues.redhat.com/browse/RHEL-144090 [rhel-9.8]
---
src/qemu/qemu_snapshot.c | 53 ++++++++++++++++++++++++++++------------
1 file changed, 38 insertions(+), 15 deletions(-)
diff --git a/src/qemu/qemu_snapshot.c b/src/qemu/qemu_snapshot.c
index c23add5103..e30ade9dc8 100644
--- a/src/qemu/qemu_snapshot.c
+++ b/src/qemu/qemu_snapshot.c
@@ -3698,25 +3698,48 @@ qemuSnapshotUpdateBackingStore(qemuSnapshotDeleteExternalData *data)
for (cur = data->disksWithBacking; cur; cur = g_slist_next(cur)) {
struct _qemuSnapshotDisksWithBackingStoreData *backingData = cur->data;
- g_autoptr(virCommand) cmd = NULL;
+ /* Try to run the command first as the appropriate user based on the
+ * domain definition and config. If error is returned retry as current
+ * (possibly privileged) user for cases where seclabels were reset
+ * to the default */
+ g_autoptr(virCommand) cmd_user_qemu = NULL;
+ g_autoptr(virCommand) cmd_user_curr = NULL;
- if (!(cmd = virCommandNewArgList("qemu-img",
- "rebase",
- "-u",
- "-F",
- virStorageFileFormatTypeToString(data->parentDiskSrc->format),
- "-f",
- virStorageFileFormatTypeToString(backingData->diskSrc->format),
- "-b",
- data->parentDiskSrc->path,
- backingData->diskSrc->path,
- NULL)))
+ if (!(cmd_user_qemu = virCommandNewArgList("qemu-img",
+ "rebase",
+ "-u",
+ "-F",
+ virStorageFileFormatTypeToString(data->parentDiskSrc->format),
+ "-f",
+ virStorageFileFormatTypeToString(backingData->diskSrc->format),
+ "-b",
+ data->parentDiskSrc->path,
+ backingData->diskSrc->path,
+ NULL)))
continue;
- virCommandSetUID(cmd, backingData->uid);
- virCommandSetGID(cmd, backingData->gid);
+ virCommandSetUID(cmd_user_qemu, backingData->uid);
+ virCommandSetGID(cmd_user_qemu, backingData->gid);
- ignore_value(virCommandRun(cmd, NULL));
+ /* done on success */
+ if (virCommandRun(cmd_user_qemu, NULL) == 0)
+ continue;
+
+ /* retry as current user */
+ if (!(cmd_user_curr = virCommandNewArgList("qemu-img",
+ "rebase",
+ "-u",
+ "-F",
+ virStorageFileFormatTypeToString(data->parentDiskSrc->format),
+ "-f",
+ virStorageFileFormatTypeToString(backingData->diskSrc->format),
+ "-b",
+ data->parentDiskSrc->path,
+ backingData->diskSrc->path,
+ NULL)))
+ continue;
+
+ ignore_value(virCommandRun(cmd_user_curr, NULL));
}
}
--
2.52.0

View File

@ -0,0 +1,172 @@
From 9daca4f4b8e914a09d86db07d1c7292a6e9e4048 Mon Sep 17 00:00:00 2001
Message-ID: <9daca4f4b8e914a09d86db07d1c7292a6e9e4048.1772815313.git.jdenemar@redhat.com>
From: Andrea Bolognani <abologna@redhat.com>
Date: Fri, 21 Nov 2025 15:34:32 +0100
Subject: [PATCH] qemu_capabilities: Introduce QEMU_CAPS_DEVICE_UEFI_VARS
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This capability indicates the availability of the uefi-vars
device.
The actual name of the QEMU device varies slightly depending on
the architecture: it's uefi-vars-x64 on x86_64, uefi-vars-sysbus
on other UEFI architectures (aarch64, riscv64, loongarch64).
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
(cherry picked from commit 12cdd613832c77d143bfa2b87539a22ec6911f6d)
Conflicts:
* tests/qemucapabilitiesdata/caps_10.1.0_s390x.xml
tests/qemucapabilitiesdata/caps_10.2.0_aarch64.xml
tests/qemucapabilitiesdata/caps_11.0.0_aarch64.xml
tests/qemucapabilitiesdata/caps_11.0.0_x86_64.xml
- Missing downstream
* tests/qemucapabilitiesdata/caps_10.1.0_x86_64+inteltdx.xml
tests/qemucapabilitiesdata/caps_10.2.0_x86_64+mshv.xml
tests/qemucapabilitiesdata/caps_10.2.0_x86_64.xml
- Trivial context conflicts caused by capabilities files
being outdated downstream
https://issues.redhat.com/browse/RHEL-82645
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
---
src/qemu/qemu_capabilities.c | 3 +++
src/qemu/qemu_capabilities.h | 1 +
tests/qemucapabilitiesdata/caps_10.0.0_aarch64.xml | 1 +
tests/qemucapabilitiesdata/caps_10.0.0_x86_64+amdsev.xml | 1 +
tests/qemucapabilitiesdata/caps_10.0.0_x86_64.xml | 1 +
tests/qemucapabilitiesdata/caps_10.1.0_x86_64+inteltdx.xml | 1 +
tests/qemucapabilitiesdata/caps_10.1.0_x86_64.xml | 1 +
tests/qemucapabilitiesdata/caps_10.2.0_x86_64+mshv.xml | 1 +
tests/qemucapabilitiesdata/caps_10.2.0_x86_64.xml | 1 +
9 files changed, 11 insertions(+)
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index 7d88b8521a..8b20ca9312 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -760,6 +760,7 @@ VIR_ENUM_IMPL(virQEMUCaps,
/* 490 */
"iommufd", /* QEMU_CAPS_OBJECT_IOMMUFD */
+ "uefi-vars", /* QEMU_CAPS_DEVICE_UEFI_VARS */
);
@@ -1468,6 +1469,8 @@ struct virQEMUCapsStringFlags virQEMUCapsObjectTypes[] = {
{ "tpm-passthrough", QEMU_CAPS_DEVICE_TPM_PASSTHROUGH },
{ "acpi-generic-initiator", QEMU_CAPS_ACPI_GENERIC_INITIATOR },
{ "iommufd", QEMU_CAPS_OBJECT_IOMMUFD },
+ { "uefi-vars-x64", QEMU_CAPS_DEVICE_UEFI_VARS },
+ { "uefi-vars-sysbus", QEMU_CAPS_DEVICE_UEFI_VARS },
};
diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
index f7c8680f94..4dcf464061 100644
--- a/src/qemu/qemu_capabilities.h
+++ b/src/qemu/qemu_capabilities.h
@@ -734,6 +734,7 @@ typedef enum { /* virQEMUCapsFlags grouping marker for syntax-check */
/* 490 */
QEMU_CAPS_OBJECT_IOMMUFD, /* -object iommufd */
+ QEMU_CAPS_DEVICE_UEFI_VARS, /* -device uefi-vars-{x64,sysbus} */
QEMU_CAPS_LAST /* this must always be the last item */
} virQEMUCapsFlags;
diff --git a/tests/qemucapabilitiesdata/caps_10.0.0_aarch64.xml b/tests/qemucapabilitiesdata/caps_10.0.0_aarch64.xml
index bbb8b33cde..1243a56fb8 100644
--- a/tests/qemucapabilitiesdata/caps_10.0.0_aarch64.xml
+++ b/tests/qemucapabilitiesdata/caps_10.0.0_aarch64.xml
@@ -164,6 +164,7 @@
<flag name='usb-bot'/>
<flag name='acpi-generic-initiator'/>
<flag name='iommufd'/>
+ <flag name='uefi-vars'/>
<version>10000000</version>
<microcodeVersion>61700285</microcodeVersion>
<package>v10.0.0</package>
diff --git a/tests/qemucapabilitiesdata/caps_10.0.0_x86_64+amdsev.xml b/tests/qemucapabilitiesdata/caps_10.0.0_x86_64+amdsev.xml
index 5acd1a33fd..cd77e934c8 100644
--- a/tests/qemucapabilitiesdata/caps_10.0.0_x86_64+amdsev.xml
+++ b/tests/qemucapabilitiesdata/caps_10.0.0_x86_64+amdsev.xml
@@ -210,6 +210,7 @@
<flag name='usb-bot'/>
<flag name='acpi-generic-initiator'/>
<flag name='iommufd'/>
+ <flag name='uefi-vars'/>
<version>10000000</version>
<microcodeVersion>43100285</microcodeVersion>
<package>v10.0.0</package>
diff --git a/tests/qemucapabilitiesdata/caps_10.0.0_x86_64.xml b/tests/qemucapabilitiesdata/caps_10.0.0_x86_64.xml
index 50f58791e6..f2567a2025 100644
--- a/tests/qemucapabilitiesdata/caps_10.0.0_x86_64.xml
+++ b/tests/qemucapabilitiesdata/caps_10.0.0_x86_64.xml
@@ -210,6 +210,7 @@
<flag name='usb-bot'/>
<flag name='acpi-generic-initiator'/>
<flag name='iommufd'/>
+ <flag name='uefi-vars'/>
<version>10000000</version>
<microcodeVersion>43100285</microcodeVersion>
<package>v10.0.0</package>
diff --git a/tests/qemucapabilitiesdata/caps_10.1.0_x86_64+inteltdx.xml b/tests/qemucapabilitiesdata/caps_10.1.0_x86_64+inteltdx.xml
index e321c352a3..a80aca9244 100644
--- a/tests/qemucapabilitiesdata/caps_10.1.0_x86_64+inteltdx.xml
+++ b/tests/qemucapabilitiesdata/caps_10.1.0_x86_64+inteltdx.xml
@@ -192,6 +192,7 @@
<flag name='tdx-guest'/>
<flag name='acpi-generic-initiator'/>
<flag name='iommufd'/>
+ <flag name='uefi-vars'/>
<version>10000050</version>
<microcodeVersion>43100286</microcodeVersion>
<package>v10.0.0-1724-gf9a3def17b</package>
diff --git a/tests/qemucapabilitiesdata/caps_10.1.0_x86_64.xml b/tests/qemucapabilitiesdata/caps_10.1.0_x86_64.xml
index 2d52659520..03790f4e31 100644
--- a/tests/qemucapabilitiesdata/caps_10.1.0_x86_64.xml
+++ b/tests/qemucapabilitiesdata/caps_10.1.0_x86_64.xml
@@ -215,6 +215,7 @@
<flag name='qom-list-get'/>
<flag name='acpi-generic-initiator'/>
<flag name='iommufd'/>
+ <flag name='uefi-vars'/>
<version>10001000</version>
<microcodeVersion>43100286</microcodeVersion>
<package>v10.1.0</package>
diff --git a/tests/qemucapabilitiesdata/caps_10.2.0_x86_64+mshv.xml b/tests/qemucapabilitiesdata/caps_10.2.0_x86_64+mshv.xml
index eb2ab001a6..0ba4d2f990 100644
--- a/tests/qemucapabilitiesdata/caps_10.2.0_x86_64+mshv.xml
+++ b/tests/qemucapabilitiesdata/caps_10.2.0_x86_64+mshv.xml
@@ -202,6 +202,7 @@
<flag name='query-accelerators'/>
<flag name='mshv'/>
<flag name='iommufd'/>
+ <flag name='uefi-vars'/>
<version>10001050</version>
<microcodeVersion>43100287</microcodeVersion>
<package>v10.1.0-1778-ge090e0312d</package>
diff --git a/tests/qemucapabilitiesdata/caps_10.2.0_x86_64.xml b/tests/qemucapabilitiesdata/caps_10.2.0_x86_64.xml
index c4ea924c1f..47bb94527f 100644
--- a/tests/qemucapabilitiesdata/caps_10.2.0_x86_64.xml
+++ b/tests/qemucapabilitiesdata/caps_10.2.0_x86_64.xml
@@ -217,6 +217,7 @@
<flag name='query-accelerators'/>
<flag name='scsi-block.migrate-pr'/>
<flag name='iommufd'/>
+ <flag name='uefi-vars'/>
<version>10001091</version>
<microcodeVersion>43100287</microcodeVersion>
<package>v10.2.0-rc1-38-gfb241d0a1f</package>
--
2.53.0

View File

@ -0,0 +1,134 @@
From 5cb651d76f287f1ae0212cf0f4d2d7618050e5d1 Mon Sep 17 00:00:00 2001
Message-ID: <5cb651d76f287f1ae0212cf0f4d2d7618050e5d1.1771423659.git.jdenemar@redhat.com>
From: Pavel Hrdina <phrdina@redhat.com>
Date: Sun, 15 Feb 2026 19:49:16 +0100
Subject: [PATCH] qemu_command: Don't use host property if IOMMUFD is used
They should not be used at the same time.
Fixes: f6230804727df834da27370e835204672218ab23
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit f67e4ac4d071f6f05ae387bc3b09c6cebb10455d)
Resolves: https://issues.redhat.com/browse/RHEL-150351
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
---
src/qemu/qemu_command.c | 24 +++++++++----------
.../iommufd-q35.x86_64-latest.args | 2 +-
...fd-virt-pci-bus-single.aarch64-latest.args | 2 +-
.../iommufd-virt.aarch64-latest.args | 4 ++--
.../iommufd.x86_64-latest.args | 2 +-
5 files changed, 16 insertions(+), 18 deletions(-)
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 33127fbc0a..d11d16e533 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -4755,10 +4755,11 @@ qemuBuildPCIHostdevDevProps(const virDomainDef *def,
g_autoptr(virJSONValue) props = NULL;
virDomainHostdevSubsysPCI *pcisrc = &dev->source.subsys.u.pci;
virDomainNetTeamingInfo *teaming;
- g_autofree char *host = virPCIDeviceAddressAsString(&pcisrc->addr);
+ g_autofree char *host = NULL;
const char *failover_pair_id = NULL;
const char *driver = NULL;
const char *iommufdId = NULL;
+ const char *fdstr = NULL;
/* 'ramfb' property must be omitted unless it's to be enabled */
bool ramfb = pcisrc->ramfb == VIR_TRISTATE_SWITCH_ON;
@@ -4792,31 +4793,28 @@ qemuBuildPCIHostdevDevProps(const virDomainDef *def,
teaming->persistent)
failover_pair_id = teaming->persistent;
- if (pcisrc->driver.iommufd == VIR_TRISTATE_BOOL_YES)
+ if (virHostdevIsPCIDeviceWithIOMMUFD(dev)) {
+ qemuDomainHostdevPrivate *hostdevPriv = QEMU_DOMAIN_HOSTDEV_PRIVATE(dev);
+
+ fdstr = qemuFDPassDirectGetPath(hostdevPriv->vfioDeviceFd);
iommufdId = "iommufd0";
+ } else {
+ host = virPCIDeviceAddressAsString(&pcisrc->addr);
+ }
if (virJSONValueObjectAdd(&props,
"s:driver", driver,
- "s:host", host,
+ "S:host", host,
"s:id", dev->info->alias,
"p:bootindex", dev->info->effectiveBootIndex,
"S:failover_pair_id", failover_pair_id,
"S:display", qemuOnOffAuto(pcisrc->display),
"B:ramfb", ramfb,
"S:iommufd", iommufdId,
+ "S:fd", fdstr,
NULL) < 0)
return NULL;
- if (pcisrc->driver.name == VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_VFIO &&
- pcisrc->driver.iommufd == VIR_TRISTATE_BOOL_YES) {
- qemuDomainHostdevPrivate *hostdevPriv = QEMU_DOMAIN_HOSTDEV_PRIVATE(dev);
-
- if (virJSONValueObjectAdd(&props,
- "S:fd", qemuFDPassDirectGetPath(hostdevPriv->vfioDeviceFd),
- NULL) < 0)
- return NULL;
- }
-
if (qemuBuildDeviceAddressProps(props, def, dev->info) < 0)
return NULL;
diff --git a/tests/qemuxmlconfdata/iommufd-q35.x86_64-latest.args b/tests/qemuxmlconfdata/iommufd-q35.x86_64-latest.args
index d5fe704021..f886c488e1 100644
--- a/tests/qemuxmlconfdata/iommufd-q35.x86_64-latest.args
+++ b/tests/qemuxmlconfdata/iommufd-q35.x86_64-latest.args
@@ -36,6 +36,6 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-q35-test/.config \
-global ICH9-LPC.noreboot=off \
-watchdog-action reset \
-object '{"qom-type":"iommufd","id":"iommufd0","fd":"0"}' \
--device '{"driver":"vfio-pci","host":"0000:06:12.5","id":"hostdev0","iommufd":"iommufd0","fd":"0","bus":"pcie.0","addr":"0x3"}' \
+-device '{"driver":"vfio-pci","id":"hostdev0","iommufd":"iommufd0","fd":"0","bus":"pcie.0","addr":"0x3"}' \
-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \
-msg timestamp=on
diff --git a/tests/qemuxmlconfdata/iommufd-virt-pci-bus-single.aarch64-latest.args b/tests/qemuxmlconfdata/iommufd-virt-pci-bus-single.aarch64-latest.args
index 99886468fb..d6562f9be3 100644
--- a/tests/qemuxmlconfdata/iommufd-virt-pci-bus-single.aarch64-latest.args
+++ b/tests/qemuxmlconfdata/iommufd-virt-pci-bus-single.aarch64-latest.args
@@ -28,6 +28,6 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-foo/.config \
-boot strict=on \
-audiodev '{"id":"audio1","driver":"none"}' \
-object '{"qom-type":"iommufd","id":"iommufd0","fd":"0"}' \
--device '{"driver":"vfio-pci","host":"0000:06:12.5","id":"hostdev0","iommufd":"iommufd0","fd":"0","bus":"pcie.0","addr":"0x1"}' \
+-device '{"driver":"vfio-pci","id":"hostdev0","iommufd":"iommufd0","fd":"0","bus":"pcie.0","addr":"0x1"}' \
-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \
-msg timestamp=on
diff --git a/tests/qemuxmlconfdata/iommufd-virt.aarch64-latest.args b/tests/qemuxmlconfdata/iommufd-virt.aarch64-latest.args
index e3695c6982..9fd2a6adee 100644
--- a/tests/qemuxmlconfdata/iommufd-virt.aarch64-latest.args
+++ b/tests/qemuxmlconfdata/iommufd-virt.aarch64-latest.args
@@ -31,7 +31,7 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-foo/.config \
-device '{"driver":"pcie-root-port","port":10,"chassis":3,"id":"pci.3","bus":"pcie.0","addr":"0x1.0x2"}' \
-audiodev '{"id":"audio1","driver":"none"}' \
-object '{"qom-type":"iommufd","id":"iommufd0","fd":"0"}' \
--device '{"driver":"vfio-pci","host":"0000:06:12.5","id":"hostdev0","iommufd":"iommufd0","fd":"0","bus":"pci.1","addr":"0x0"}' \
--device '{"driver":"vfio-pci","host":"0000:07:12.5","id":"hostdev1","iommufd":"iommufd0","fd":"0","bus":"pci.2","addr":"0x0"}' \
+-device '{"driver":"vfio-pci","id":"hostdev0","iommufd":"iommufd0","fd":"0","bus":"pci.1","addr":"0x0"}' \
+-device '{"driver":"vfio-pci","id":"hostdev1","iommufd":"iommufd0","fd":"0","bus":"pci.2","addr":"0x0"}' \
-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \
-msg timestamp=on
diff --git a/tests/qemuxmlconfdata/iommufd.x86_64-latest.args b/tests/qemuxmlconfdata/iommufd.x86_64-latest.args
index 15dabe197c..b9aefda39d 100644
--- a/tests/qemuxmlconfdata/iommufd.x86_64-latest.args
+++ b/tests/qemuxmlconfdata/iommufd.x86_64-latest.args
@@ -29,7 +29,7 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-foo/.config \
-device '{"driver":"piix3-usb-uhci","id":"usb","bus":"pci.0","addr":"0x1.0x2"}' \
-audiodev '{"id":"audio1","driver":"none"}' \
-object '{"qom-type":"iommufd","id":"iommufd0","fd":"0"}' \
--device '{"driver":"vfio-pci","host":"0000:06:12.5","id":"hostdev0","iommufd":"iommufd0","fd":"0","bus":"pci.0","addr":"0x3"}' \
+-device '{"driver":"vfio-pci","id":"hostdev0","iommufd":"iommufd0","fd":"0","bus":"pci.0","addr":"0x3"}' \
-device '{"driver":"virtio-balloon-pci","id":"balloon0","bus":"pci.0","addr":"0x2"}' \
-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \
-msg timestamp=on
--
2.53.0

View File

@ -0,0 +1,73 @@
From e5bdfe01cb976c45a440b88061a40f65ac6f8be8 Mon Sep 17 00:00:00 2001
Message-ID: <e5bdfe01cb976c45a440b88061a40f65ac6f8be8.1771423659.git.jdenemar@redhat.com>
From: Pavel Hrdina <phrdina@redhat.com>
Date: Sun, 15 Feb 2026 20:10:50 +0100
Subject: [PATCH] qemu_command: Extract building IOMMUFD props to function
This will be reused by hotplug code.
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit 3f7ad3a8a5f0e453c85f186e811e051ead0f769a)
Resolves: https://issues.redhat.com/browse/RHEL-150351
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
---
src/qemu/qemu_command.c | 20 ++++++++++++++++----
src/qemu/qemu_command.h | 3 +++
2 files changed, 19 insertions(+), 4 deletions(-)
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index cca5fed285..521aefbc10 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -5337,6 +5337,21 @@ qemuBuildHostdevCommandLine(virCommand *cmd,
}
+virJSONValue *
+qemuBuildIOMMUFDProps(qemuFDPassDirect *iommufd)
+{
+ g_autoptr(virJSONValue) props = NULL;
+
+ if (qemuMonitorCreateObjectProps(&props, "iommufd",
+ "iommufd0",
+ "S:fd", qemuFDPassDirectGetPath(iommufd),
+ NULL) < 0)
+ return NULL;
+
+ return g_steal_pointer(&props);
+}
+
+
static int
qemuBuildIOMMUFDCommandLine(virCommand *cmd,
const virDomainDef *def,
@@ -5350,10 +5365,7 @@ qemuBuildIOMMUFDCommandLine(virCommand *cmd,
qemuFDPassDirectTransferCommand(priv->iommufd, cmd);
- if (qemuMonitorCreateObjectProps(&props, "iommufd",
- "iommufd0",
- "S:fd", qemuFDPassDirectGetPath(priv->iommufd),
- NULL) < 0)
+ if (!(props = qemuBuildIOMMUFDProps(priv->iommufd)))
return -1;
if (qemuBuildObjectCommandlineFromJSON(cmd, props) < 0)
diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h
index ad068f1f16..028d002ef9 100644
--- a/src/qemu/qemu_command.h
+++ b/src/qemu/qemu_command.h
@@ -190,6 +190,9 @@ int
qemuBuildRNGBackendProps(virDomainRNGDef *rng,
virJSONValue **props);
+virJSONValue *
+qemuBuildIOMMUFDProps(qemuFDPassDirect *iommufd);
+
/* Current, best practice */
virJSONValue *
qemuBuildUSBHostdevDevProps(const virDomainDef *def,
--
2.53.0

View File

@ -0,0 +1,154 @@
From 71ed9b3cb411e469d78fd5203799f3086127b9c3 Mon Sep 17 00:00:00 2001
Message-ID: <71ed9b3cb411e469d78fd5203799f3086127b9c3.1772815314.git.jdenemar@redhat.com>
From: Andrea Bolognani <abologna@redhat.com>
Date: Tue, 11 Nov 2025 15:33:41 +0100
Subject: [PATCH] qemu_command: Use uefi-vars device where appropriate
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This makes guests actually functional.
https://issues.redhat.com/browse/RHEL-82645
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
(cherry picked from commit bcda5b2efdf7c3472fd15dc758aad6842c214481)
Conflicts:
* tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.aarch64-latest.args
tests/qemuxmlconfdata/firmware-auto-efi-varstore-aarch64.aarch64-latest.args
tests/qemuxmlconfdata/firmware-manual-efi-varstore-aarch64.aarch64-latest.args
- GIC version mismatch caused by capabilities files
being outdated or missing downstream
https://issues.redhat.com/browse/RHEL-82645
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
---
src/qemu/qemu_command.c | 34 +++++++++++++++++++
...-enrolled-keys-aarch64.aarch64-latest.args | 1 +
...o-efi-varstore-aarch64.aarch64-latest.args | 1 +
...e-auto-efi-varstore-q35.x86_64-latest.args | 1 +
...l-efi-varstore-aarch64.aarch64-latest.args | 1 +
...manual-efi-varstore-q35.x86_64-latest.args | 1 +
6 files changed, 39 insertions(+)
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 521aefbc10..7b1b470398 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -9788,6 +9788,37 @@ qemuBuildDomainLoaderCommandLine(virCommand *cmd,
}
+static int
+qemuBuildUefiVarsCommandLine(virCommand *cmd,
+ const virDomainDef *def,
+ virQEMUCaps *qemuCaps)
+{
+ virDomainLoaderDef *loader = def->os.loader;
+ virDomainVarstoreDef *varstore = def->os.varstore;
+ g_autoptr(virJSONValue) props = NULL;
+ const char *model = NULL;
+
+ if (!loader || !varstore || !varstore->path)
+ return 0;
+
+ if (ARCH_IS_X86(def->os.arch))
+ model = "uefi-vars-x64";
+ else
+ model = "uefi-vars-sysbus";
+
+ if (virJSONValueObjectAdd(&props,
+ "s:driver", model,
+ "s:jsonfile", varstore->path,
+ NULL) < 0)
+ return -1;
+
+ if (qemuBuildDeviceCommandlineFromJSON(cmd, props, def, qemuCaps) < 0)
+ return -1;
+
+ return 0;
+}
+
+
static int
qemuBuildTPMDevCmd(virCommand *cmd,
const virDomainDef *def,
@@ -10862,6 +10893,9 @@ qemuBuildCommandLine(virDomainObj *vm,
qemuBuildDomainLoaderCommandLine(cmd, def);
+ if (qemuBuildUefiVarsCommandLine(cmd, def, qemuCaps) < 0)
+ return NULL;
+
if (qemuBuildMemCommandLine(cmd, def, qemuCaps, priv) < 0)
return NULL;
diff --git a/tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.aarch64-latest.args b/tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.aarch64-latest.args
index 1cd04c87b1..caf1933091 100644
--- a/tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.aarch64-latest.args
+++ b/tests/qemuxmlconfdata/firmware-auto-efi-enrolled-keys-aarch64.aarch64-latest.args
@@ -13,6 +13,7 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-guest/.config \
-machine virt-8.2,usb=off,gic-version=3,dump-guest-core=off,memory-backend=mach-virt.ram,acpi=on \
-accel kvm \
-bios /usr/share/edk2/aarch64/QEMU_EFI.qemuvars.fd \
+-device '{"driver":"uefi-vars-sysbus","jsonfile":"/var/lib/libvirt/qemu/varstore/guest.json"}' \
-m size=1048576k \
-object '{"qom-type":"memory-backend-ram","id":"mach-virt.ram","size":1073741824}' \
-overcommit mem-lock=off \
diff --git a/tests/qemuxmlconfdata/firmware-auto-efi-varstore-aarch64.aarch64-latest.args b/tests/qemuxmlconfdata/firmware-auto-efi-varstore-aarch64.aarch64-latest.args
index 1cd04c87b1..caf1933091 100644
--- a/tests/qemuxmlconfdata/firmware-auto-efi-varstore-aarch64.aarch64-latest.args
+++ b/tests/qemuxmlconfdata/firmware-auto-efi-varstore-aarch64.aarch64-latest.args
@@ -13,6 +13,7 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-guest/.config \
-machine virt-8.2,usb=off,gic-version=3,dump-guest-core=off,memory-backend=mach-virt.ram,acpi=on \
-accel kvm \
-bios /usr/share/edk2/aarch64/QEMU_EFI.qemuvars.fd \
+-device '{"driver":"uefi-vars-sysbus","jsonfile":"/var/lib/libvirt/qemu/varstore/guest.json"}' \
-m size=1048576k \
-object '{"qom-type":"memory-backend-ram","id":"mach-virt.ram","size":1073741824}' \
-overcommit mem-lock=off \
diff --git a/tests/qemuxmlconfdata/firmware-auto-efi-varstore-q35.x86_64-latest.args b/tests/qemuxmlconfdata/firmware-auto-efi-varstore-q35.x86_64-latest.args
index 9a899c2a65..392ea77c28 100644
--- a/tests/qemuxmlconfdata/firmware-auto-efi-varstore-q35.x86_64-latest.args
+++ b/tests/qemuxmlconfdata/firmware-auto-efi-varstore-q35.x86_64-latest.args
@@ -14,6 +14,7 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-guest/.config \
-accel kvm \
-cpu qemu64 \
-bios /usr/share/edk2/ovmf/OVMF.qemuvars.fd \
+-device '{"driver":"uefi-vars-x64","jsonfile":"/var/lib/libvirt/qemu/varstore/guest.json"}' \
-m size=1048576k \
-object '{"qom-type":"memory-backend-ram","id":"pc.ram","size":1073741824}' \
-overcommit mem-lock=off \
diff --git a/tests/qemuxmlconfdata/firmware-manual-efi-varstore-aarch64.aarch64-latest.args b/tests/qemuxmlconfdata/firmware-manual-efi-varstore-aarch64.aarch64-latest.args
index 1cd04c87b1..1989405e07 100644
--- a/tests/qemuxmlconfdata/firmware-manual-efi-varstore-aarch64.aarch64-latest.args
+++ b/tests/qemuxmlconfdata/firmware-manual-efi-varstore-aarch64.aarch64-latest.args
@@ -13,6 +13,7 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-guest/.config \
-machine virt-8.2,usb=off,gic-version=3,dump-guest-core=off,memory-backend=mach-virt.ram,acpi=on \
-accel kvm \
-bios /usr/share/edk2/aarch64/QEMU_EFI.qemuvars.fd \
+-device '{"driver":"uefi-vars-sysbus","jsonfile":"/path/to/guest.json"}' \
-m size=1048576k \
-object '{"qom-type":"memory-backend-ram","id":"mach-virt.ram","size":1073741824}' \
-overcommit mem-lock=off \
diff --git a/tests/qemuxmlconfdata/firmware-manual-efi-varstore-q35.x86_64-latest.args b/tests/qemuxmlconfdata/firmware-manual-efi-varstore-q35.x86_64-latest.args
index 9a899c2a65..6c04c8c39f 100644
--- a/tests/qemuxmlconfdata/firmware-manual-efi-varstore-q35.x86_64-latest.args
+++ b/tests/qemuxmlconfdata/firmware-manual-efi-varstore-q35.x86_64-latest.args
@@ -14,6 +14,7 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-guest/.config \
-accel kvm \
-cpu qemu64 \
-bios /usr/share/edk2/ovmf/OVMF.qemuvars.fd \
+-device '{"driver":"uefi-vars-x64","jsonfile":"/path/to/guest.json"}' \
-m size=1048576k \
-object '{"qom-type":"memory-backend-ram","id":"pc.ram","size":1073741824}' \
-overcommit mem-lock=off \
--
2.53.0

View File

@ -0,0 +1,33 @@
From 31d95c7ad884094f2afd4a0f2450141cc68594ff Mon Sep 17 00:00:00 2001
Message-ID: <31d95c7ad884094f2afd4a0f2450141cc68594ff.1771423658.git.jdenemar@redhat.com>
From: Pavel Hrdina <phrdina@redhat.com>
Date: Sat, 14 Feb 2026 16:12:11 +0100
Subject: [PATCH] qemu_domain: Add missing IOMMUFD cleanup
If starting VM fails we would leak the FD for IOMMU device.
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit 7c062bfc4f8c0ba853873e72d21dba77f6ca938f)
Resolves: https://issues.redhat.com/browse/RHEL-150351
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
---
src/qemu/qemu_domain.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index bdab117e96..64b01e524f 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -1975,6 +1975,8 @@ qemuDomainObjPrivateDataClear(qemuDomainObjPrivate *priv)
priv->migrationRecoverSetup = false;
+ VIR_FORCE_CLOSE(priv->iommufd);
+
g_clear_pointer(&priv->memoryBackingDir, g_free);
}
--
2.53.0

View File

@ -1,105 +0,0 @@
From f34372c108e5b4f1e37c333a7ff2c50faa9f534e Mon Sep 17 00:00:00 2001
Message-ID: <f34372c108e5b4f1e37c333a7ff2c50faa9f534e.1723213495.git.jdenemar@redhat.com>
From: Peter Krempa <pkrempa@redhat.com>
Date: Wed, 31 Jul 2024 11:34:59 +0200
Subject: [PATCH] qemu_domain: Strip <acpi/> from s390(x) definitions
The s390(x) machines never supported ACPI. That didn't stop users
enabling ACPI in their config. As of libvirt-9.2 (98c4e3d073) with new
enough qemu we reject configs which require ACPI, but qemu can't satisfy
it.
This breaks migration of existing VMs with the old wrong configs to new
libvirt installations.
To address this introduce a post-parse fixup removing the ACPI flag
specifically for s390 machines which do enable it in the definition.
The advantage of doing it in post-parse, rather than simply relaxing the
ABI stability check to allow users providing an fixed XML when migrating
(allowing change of the ACPI flag for s390 in ABI stability check, as it
doesn't impact ABI), is that only the destination installation needs to
be patched in order to preserve migration.
To mitigate the disadvantage of simply stripping it from all s390(x)
configs the hack is not applied when defining or starting a new domain
from the XML, to preserve the error about unsupported configuration.
Resolves: https://issues.redhat.com/browse/RHEL-49516
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Andrea Bolognani <abologna@redhat.com>
Reviewed-by: Boris Fiuczynski <fiuczy@linux.ibm.com>
(cherry picked from commit 4ba4f659e42a30c3fa8ece414616a23a992acfaa)
---
src/qemu/qemu_domain.c | 49 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 49 insertions(+)
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 1a90311ca5..1bafe3708a 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -5013,6 +5013,53 @@ qemuDomainDefPostParseBasic(virDomainDef *def,
}
+/**
+ * qemuDomainDefACPIPostParse:
+ * @def: domain definition
+ * @qemuCaps: qemu capabilities object
+ *
+ * Fixup the use of ACPI flag on certain architectures that never supported it
+ * and users for some reason used it, which would break migration to newer
+ * libvirt versions which check whether given machine type supports ACPI.
+ *
+ * The fixup is done in post-parse as it's hard to update the ABI stability
+ * check on source of the migration.
+ */
+static void
+qemuDomainDefACPIPostParse(virDomainDef *def,
+ virQEMUCaps *qemuCaps,
+ unsigned int parseFlags)
+{
+ /* Only cases when ACPI is enabled need to be fixed up */
+ if (def->features[VIR_DOMAIN_FEATURE_ACPI] != VIR_TRISTATE_SWITCH_ON)
+ return;
+
+ /* Strip the <acpi/> feature only for non-fresh configs, in order to still
+ * produce an error if the feature is present in a newly defined one.
+ *
+ * The use of the VIR_DOMAIN_DEF_PARSE_ABI_UPDATE looks counter-intuitive,
+ * but it's used only in qemuDomainCreateXML/qemuDomainDefineXMLFlags APIs
+ * */
+ if (parseFlags & VIR_DOMAIN_DEF_PARSE_ABI_UPDATE)
+ return;
+
+ /* This fixup is applicable _only_ on architectures which were present as of
+ * libvirt-9.2 and *never* supported ACPI. The fixup is currently done only
+ * for existing users of s390(x) to fix migration for configs which had
+ * <acpi/> despite being ignored.
+ */
+ if (def->os.arch != VIR_ARCH_S390 &&
+ def->os.arch != VIR_ARCH_S390X)
+ return;
+
+ /* To be sure, we only strip ACPI if given machine type doesn't support it */
+ if (virQEMUCapsMachineSupportsACPI(qemuCaps, def->virtType, def->os.machine) != VIR_TRISTATE_BOOL_NO)
+ return;
+
+ def->features[VIR_DOMAIN_FEATURE_ACPI] = VIR_TRISTATE_SWITCH_ABSENT;
+}
+
+
static int
qemuDomainDefPostParse(virDomainDef *def,
unsigned int parseFlags,
@@ -5033,6 +5080,8 @@ qemuDomainDefPostParse(virDomainDef *def,
if (qemuDomainDefMachinePostParse(def, qemuCaps) < 0)
return -1;
+ qemuDomainDefACPIPostParse(def, qemuCaps, parseFlags);
+
if (qemuDomainDefBootPostParse(def, driver, parseFlags) < 0)
return -1;
--
2.46.0

View File

@ -0,0 +1,131 @@
From a11c975eb05296487023db1beb72d5575af6b05a Mon Sep 17 00:00:00 2001
Message-ID: <a11c975eb05296487023db1beb72d5575af6b05a.1772815313.git.jdenemar@redhat.com>
From: Andrea Bolognani <abologna@redhat.com>
Date: Mon, 17 Nov 2025 18:02:15 +0100
Subject: [PATCH] qemu_firmware: Allow matching both UEFI and BIOS for ROM
loader
Currently we apply a 1:1 mapping between loader type and firmware
type: ROM can only match BIOS and pflash can only match UEFI.
That was accurate at the time when the check was introduced, but
is no longer the case today: the Intel TDX build of edk2, for
example, is loaded as a ROM but it still provides an UEFI
implementation to the guest.
Tweak the matching logic so that a ROM loader is allowed to match
both BIOS and UEFI firmware descriptors.
The firmware-manual-efi-tdx test case benefits from this change,
as all the missing information is now correctly filled in.
This will also solve an issue reported to the list, where
firmware builds targeting the confidential VM use case on aarch64
would not be usable at all, due to the way UEFI and ACPI are
depending on each other on the architecture.
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit 563a47ea7fc255c08d834f8a2d0956bae84317a9)
https://issues.redhat.com/browse/RHEL-82645
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
---
src/qemu/qemu_firmware.c | 43 +++++++++++--------
...-manual-efi-tdx.x86_64-latest+inteltdx.xml | 6 ++-
2 files changed, 30 insertions(+), 19 deletions(-)
diff --git a/src/qemu/qemu_firmware.c b/src/qemu/qemu_firmware.c
index 7953b297bc..52205b72f8 100644
--- a/src/qemu/qemu_firmware.c
+++ b/src/qemu/qemu_firmware.c
@@ -937,23 +937,6 @@ qemuFirmwareOSInterfaceTypeToOsDefFirmware(qemuFirmwareOSInterface interface)
}
-static qemuFirmwareOSInterface
-qemuFirmwareOSInterfaceTypeFromOsDefLoaderType(virDomainLoader type)
-{
- switch (type) {
- case VIR_DOMAIN_LOADER_TYPE_ROM:
- return QEMU_FIRMWARE_OS_INTERFACE_BIOS;
- case VIR_DOMAIN_LOADER_TYPE_PFLASH:
- return QEMU_FIRMWARE_OS_INTERFACE_UEFI;
- case VIR_DOMAIN_LOADER_TYPE_NONE:
- case VIR_DOMAIN_LOADER_TYPE_LAST:
- break;
- }
-
- return QEMU_FIRMWARE_OS_INTERFACE_NONE;
-}
-
-
/**
* qemuFirmwareEnsureNVRAM:
* @def: domain definition
@@ -1100,6 +1083,8 @@ qemuFirmwareMatchDomain(const virDomainDef *def,
const virDomainLoaderDef *loader = def->os.loader;
size_t i;
qemuFirmwareOSInterface want;
+ bool wantUEFI = false;
+ bool wantBIOS = false;
bool supportsS3 = false;
bool supportsS4 = false;
bool requiresSMM = false;
@@ -1115,12 +1100,34 @@ qemuFirmwareMatchDomain(const virDomainDef *def,
want = qemuFirmwareOSInterfaceTypeFromOsDefFirmware(def->os.firmware);
if (want == QEMU_FIRMWARE_OS_INTERFACE_NONE && loader) {
- want = qemuFirmwareOSInterfaceTypeFromOsDefLoaderType(loader->type);
+ /* If an explicit request for a specific type of firmware is
+ * not present, we can still infer this information from
+ * other factors. Specifically, the pflash loader type is
+ * only used for UEFI, while the rom loader type can be used
+ * both for UEFI and BIOS */
+ switch (loader->type) {
+ case VIR_DOMAIN_LOADER_TYPE_PFLASH:
+ wantUEFI = true;
+ break;
+ case VIR_DOMAIN_LOADER_TYPE_ROM:
+ wantUEFI = true;
+ wantBIOS = true;
+ break;
+ case VIR_DOMAIN_LOADER_TYPE_NONE:
+ case VIR_DOMAIN_LOADER_TYPE_LAST:
+ default:
+ break;
+ }
}
for (i = 0; i < fw->ninterfaces; i++) {
if (fw->interfaces[i] == want)
break;
+
+ if ((fw->interfaces[i] == QEMU_FIRMWARE_OS_INTERFACE_UEFI && wantUEFI) ||
+ (fw->interfaces[i] == QEMU_FIRMWARE_OS_INTERFACE_BIOS && wantBIOS)) {
+ break;
+ }
}
if (i == fw->ninterfaces) {
diff --git a/tests/qemuxmlconfdata/firmware-manual-efi-tdx.x86_64-latest+inteltdx.xml b/tests/qemuxmlconfdata/firmware-manual-efi-tdx.x86_64-latest+inteltdx.xml
index cdb92dcf1d..5b87857425 100644
--- a/tests/qemuxmlconfdata/firmware-manual-efi-tdx.x86_64-latest+inteltdx.xml
+++ b/tests/qemuxmlconfdata/firmware-manual-efi-tdx.x86_64-latest+inteltdx.xml
@@ -4,8 +4,12 @@
<memory unit='KiB'>1048576</memory>
<currentMemory unit='KiB'>1048576</currentMemory>
<vcpu placement='static'>1</vcpu>
- <os>
+ <os firmware='efi'>
<type arch='x86_64' machine='pc-q35-10.0'>hvm</type>
+ <firmware>
+ <feature enabled='yes' name='enrolled-keys'/>
+ <feature enabled='yes' name='secure-boot'/>
+ </firmware>
<loader readonly='yes' type='rom' format='raw'>/usr/share/edk2/ovmf/OVMF.inteltdx.secboot.fd</loader>
<boot dev='hd'/>
</os>
--
2.53.0

View File

@ -0,0 +1,259 @@
From fccbbe89fadebe350bf2452ef4dd3368bcf41803 Mon Sep 17 00:00:00 2001
Message-ID: <fccbbe89fadebe350bf2452ef4dd3368bcf41803.1772815313.git.jdenemar@redhat.com>
From: Andrea Bolognani <abologna@redhat.com>
Date: Mon, 19 Jan 2026 18:48:50 +0100
Subject: [PATCH] qemu_firmware: Allow matching stateful ROMs
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Stateful ROMs are those that use the uefi-vars QEMU device to
implement access to UEFI variable storage.
Matching works much the same as it does for pflash-based
firmware images. Notably, the <varstore> element is only
allowed for ROM and the <nvram> element is only allowed for
pflash.
The firmware-auto-efi-varstore-q35 and
firmware-auto-efi-varstore-aarch64 fail in a different way
after this change: the input XML is now considered valid, and
the only remaining issue is that the firmware autoselection
process is unable to find a match.
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
(cherry picked from commit fa74aae490f9f13c469eba8b3837ab8cd84c64fd)
Conflicts:
* tests/qemuxmlconfdata/firmware-auto-efi-varstore-aarch64.aarch64-latest.xml
- GIC version mismatch caused by capabilities files
being outdated or missing downstream
https://issues.redhat.com/browse/RHEL-82645
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
---
src/qemu/qemu_firmware.c | 40 +++++++++++++++++--
...to-efi-varstore-aarch64.aarch64-latest.err | 2 +-
...to-efi-varstore-aarch64.aarch64-latest.xml | 28 +++++++++++++
...re-auto-efi-varstore-q35.x86_64-latest.err | 2 +-
...re-auto-efi-varstore-q35.x86_64-latest.xml | 36 +++++++++++++++++
tests/qemuxmlconftest.c | 4 +-
6 files changed, 104 insertions(+), 8 deletions(-)
create mode 100644 tests/qemuxmlconfdata/firmware-auto-efi-varstore-aarch64.aarch64-latest.xml
create mode 100644 tests/qemuxmlconfdata/firmware-auto-efi-varstore-q35.x86_64-latest.xml
diff --git a/src/qemu/qemu_firmware.c b/src/qemu/qemu_firmware.c
index 1851ed4a80..60635b559f 100644
--- a/src/qemu/qemu_firmware.c
+++ b/src/qemu/qemu_firmware.c
@@ -893,15 +893,18 @@ qemuFirmwareMatchesMachineArch(const qemuFirmware *fw,
* qemuFirmwareMatchesPaths:
* @fw: firmware definition
* @loader: loader definition
+ * @varstore: varstore definition
*
* Checks whether @fw is compatible with the information provided as
* part of the domain definition.
*
- * Returns: true if @fw is compatible with @loader, false otherwise
+ * Returns: true if @fw is compatible with @loader and @varstore,
+ * false otherwise
*/
static bool
qemuFirmwareMatchesPaths(const qemuFirmware *fw,
- const virDomainLoaderDef *loader)
+ const virDomainLoaderDef *loader,
+ const virDomainVarstoreDef *varstore)
{
const qemuFirmwareMappingFlash *flash = &fw->mapping.data.flash;
const qemuFirmwareMappingMemory *memory = &fw->mapping.data.memory;
@@ -922,6 +925,9 @@ qemuFirmwareMatchesPaths(const qemuFirmware *fw,
if (loader && loader->path &&
!virFileComparePaths(loader->path, memory->filename))
return false;
+ if (varstore && varstore->template &&
+ !virFileComparePaths(varstore->template, memory->template))
+ return false;
break;
case QEMU_FIRMWARE_DEVICE_NONE:
case QEMU_FIRMWARE_DEVICE_LAST:
@@ -1112,6 +1118,7 @@ qemuFirmwareMatchDomain(const virDomainDef *def,
const char *path)
{
const virDomainLoaderDef *loader = def->os.loader;
+ const virDomainVarstoreDef *varstore = def->os.varstore;
size_t i;
qemuFirmwareOSInterface want;
bool wantUEFI = false;
@@ -1166,7 +1173,7 @@ qemuFirmwareMatchDomain(const virDomainDef *def,
return false;
}
- if (!qemuFirmwareMatchesPaths(fw, def->os.loader)) {
+ if (!qemuFirmwareMatchesPaths(fw, def->os.loader, def->os.varstore)) {
VIR_DEBUG("No matching path in '%s'", path);
return false;
}
@@ -1279,6 +1286,9 @@ qemuFirmwareMatchDomain(const virDomainDef *def,
if (fw->mapping.device == QEMU_FIRMWARE_DEVICE_FLASH) {
const qemuFirmwareMappingFlash *flash = &fw->mapping.data.flash;
+ if (varstore)
+ return false;
+
if (loader && loader->type &&
loader->type != VIR_DOMAIN_LOADER_TYPE_PFLASH) {
VIR_DEBUG("Discarding flash loader");
@@ -1377,16 +1387,38 @@ qemuFirmwareMatchDomain(const virDomainDef *def,
}
}
} else if (fw->mapping.device == QEMU_FIRMWARE_DEVICE_MEMORY) {
+ const qemuFirmwareMappingMemory *memory = &fw->mapping.data.memory;
+
+ if (loader && loader->nvram)
+ return false;
+
if (loader && loader->type &&
loader->type != VIR_DOMAIN_LOADER_TYPE_ROM) {
VIR_DEBUG("Discarding rom loader");
return false;
}
- if (loader && loader->stateless == VIR_TRISTATE_BOOL_NO) {
+ /* Explicit requests for either a stateless or stateful
+ * firmware should be fulfilled, but if no preference is
+ * provided either one is fine as long as the other match
+ * criteria are satisfied. varstore implies stateful */
+ if (loader &&
+ loader->stateless == VIR_TRISTATE_BOOL_NO &&
+ !memory->template) {
VIR_DEBUG("Discarding stateless loader");
return false;
}
+ if (varstore &&
+ !memory->template) {
+ VIR_DEBUG("Discarding stateless loader");
+ return false;
+ }
+ if (loader &&
+ loader->stateless == VIR_TRISTATE_BOOL_YES &&
+ memory->template) {
+ VIR_DEBUG("Discarding non-stateless loader");
+ return false;
+ }
if (loader && loader->readonly == VIR_TRISTATE_BOOL_NO) {
VIR_DEBUG("Discarding readonly loader");
diff --git a/tests/qemuxmlconfdata/firmware-auto-efi-varstore-aarch64.aarch64-latest.err b/tests/qemuxmlconfdata/firmware-auto-efi-varstore-aarch64.aarch64-latest.err
index b45d304221..3edb2b3451 100644
--- a/tests/qemuxmlconfdata/firmware-auto-efi-varstore-aarch64.aarch64-latest.err
+++ b/tests/qemuxmlconfdata/firmware-auto-efi-varstore-aarch64.aarch64-latest.err
@@ -1 +1 @@
-Only one of NVRAM/varstore can be used
+operation failed: Unable to find 'efi' firmware that is compatible with the current configuration
diff --git a/tests/qemuxmlconfdata/firmware-auto-efi-varstore-aarch64.aarch64-latest.xml b/tests/qemuxmlconfdata/firmware-auto-efi-varstore-aarch64.aarch64-latest.xml
new file mode 100644
index 0000000000..867d8f03e3
--- /dev/null
+++ b/tests/qemuxmlconfdata/firmware-auto-efi-varstore-aarch64.aarch64-latest.xml
@@ -0,0 +1,28 @@
+<domain type='kvm'>
+ <name>guest</name>
+ <uuid>63840878-0deb-4095-97e6-fc444d9bc9fa</uuid>
+ <memory unit='KiB'>1048576</memory>
+ <currentMemory unit='KiB'>1048576</currentMemory>
+ <vcpu placement='static'>1</vcpu>
+ <os firmware='efi'>
+ <type arch='aarch64' machine='virt-8.2'>hvm</type>
+ <loader format='raw'/>
+ <varstore/>
+ <boot dev='hd'/>
+ </os>
+ <features>
+ <acpi/>
+ <gic version='3'/>
+ </features>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <emulator>/usr/bin/qemu-system-aarch64</emulator>
+ <controller type='usb' index='0' model='none'/>
+ <controller type='pci' index='0' model='pcie-root'/>
+ <audio id='1' type='none'/>
+ <memballoon model='none'/>
+ </devices>
+</domain>
diff --git a/tests/qemuxmlconfdata/firmware-auto-efi-varstore-q35.x86_64-latest.err b/tests/qemuxmlconfdata/firmware-auto-efi-varstore-q35.x86_64-latest.err
index b45d304221..3edb2b3451 100644
--- a/tests/qemuxmlconfdata/firmware-auto-efi-varstore-q35.x86_64-latest.err
+++ b/tests/qemuxmlconfdata/firmware-auto-efi-varstore-q35.x86_64-latest.err
@@ -1 +1 @@
-Only one of NVRAM/varstore can be used
+operation failed: Unable to find 'efi' firmware that is compatible with the current configuration
diff --git a/tests/qemuxmlconfdata/firmware-auto-efi-varstore-q35.x86_64-latest.xml b/tests/qemuxmlconfdata/firmware-auto-efi-varstore-q35.x86_64-latest.xml
new file mode 100644
index 0000000000..c4d70c9fc5
--- /dev/null
+++ b/tests/qemuxmlconfdata/firmware-auto-efi-varstore-q35.x86_64-latest.xml
@@ -0,0 +1,36 @@
+<domain type='kvm'>
+ <name>guest</name>
+ <uuid>63840878-0deb-4095-97e6-fc444d9bc9fa</uuid>
+ <memory unit='KiB'>1048576</memory>
+ <currentMemory unit='KiB'>1048576</currentMemory>
+ <vcpu placement='static'>1</vcpu>
+ <os firmware='efi'>
+ <type arch='x86_64' machine='pc-q35-8.2'>hvm</type>
+ <loader format='raw'/>
+ <varstore/>
+ <boot dev='hd'/>
+ </os>
+ <features>
+ <acpi/>
+ </features>
+ <cpu mode='custom' match='exact' check='none'>
+ <model fallback='forbid'>qemu64</model>
+ </cpu>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <emulator>/usr/bin/qemu-system-x86_64</emulator>
+ <controller type='usb' index='0' model='none'/>
+ <controller type='sata' index='0'>
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x1f' function='0x2'/>
+ </controller>
+ <controller type='pci' index='0' model='pcie-root'/>
+ <input type='mouse' bus='ps2'/>
+ <input type='keyboard' bus='ps2'/>
+ <audio id='1' type='none'/>
+ <watchdog model='itco' action='reset'/>
+ <memballoon model='none'/>
+ </devices>
+</domain>
diff --git a/tests/qemuxmlconftest.c b/tests/qemuxmlconftest.c
index 48c2649aa5..e38a80c57a 100644
--- a/tests/qemuxmlconftest.c
+++ b/tests/qemuxmlconftest.c
@@ -1667,8 +1667,8 @@ mymain(void)
DO_TEST_CAPS_LATEST("firmware-auto-efi-nvram-file");
DO_TEST_CAPS_LATEST("firmware-auto-efi-nvram-network-nbd");
DO_TEST_CAPS_LATEST("firmware-auto-efi-nvram-network-iscsi");
- DO_TEST_CAPS_LATEST_PARSE_ERROR("firmware-auto-efi-varstore-q35");
- DO_TEST_CAPS_ARCH_LATEST_PARSE_ERROR("firmware-auto-efi-varstore-aarch64", "aarch64");
+ DO_TEST_CAPS_LATEST_FAILURE("firmware-auto-efi-varstore-q35");
+ DO_TEST_CAPS_ARCH_LATEST_FAILURE("firmware-auto-efi-varstore-aarch64", "aarch64");
DO_TEST_CAPS_LATEST("firmware-auto-efi-format-loader-qcow2");
DO_TEST_CAPS_LATEST_PARSE_ERROR("firmware-auto-efi-format-loader-qcow2-rom");
--
2.53.0

View File

@ -0,0 +1,83 @@
From 483c5c561743c4e685ffce1d238527f13c8e83a3 Mon Sep 17 00:00:00 2001
Message-ID: <483c5c561743c4e685ffce1d238527f13c8e83a3.1772815313.git.jdenemar@redhat.com>
From: Andrea Bolognani <abologna@redhat.com>
Date: Mon, 24 Nov 2025 14:42:45 +0100
Subject: [PATCH] qemu_firmware: Consider host-uefi-vars feature in sanity
check
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Just like with firmware builds targeting the confidential use
case, use of the uefi-vars device obviates the need to have SMM
emulation enabled while still guaranteeing that protected EFI
variables work as intended.
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
(cherry picked from commit d0c6aa084f53c0c856d00b87255a31fbbc1237ad)
https://issues.redhat.com/browse/RHEL-82645
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
---
src/qemu/qemu_firmware.c | 14 ++++++++++++--
1 file changed, 12 insertions(+), 2 deletions(-)
diff --git a/src/qemu/qemu_firmware.c b/src/qemu/qemu_firmware.c
index 5c923b5a02..f9cb9058ac 100644
--- a/src/qemu/qemu_firmware.c
+++ b/src/qemu/qemu_firmware.c
@@ -1552,6 +1552,7 @@ qemuFirmwareSanityCheck(const qemuFirmware *fw,
bool requiresSMM = false;
bool supportsSecureBoot = false;
bool hasEnrolledKeys = false;
+ bool usesUefiVarsDevice = false;
bool isConfidential = false;
for (i = 0; i < fw->nfeatures; i++) {
@@ -1565,6 +1566,9 @@ qemuFirmwareSanityCheck(const qemuFirmware *fw,
case QEMU_FIRMWARE_FEATURE_ENROLLED_KEYS:
hasEnrolledKeys = true;
break;
+ case QEMU_FIRMWARE_FEATURE_HOST_UEFI_VARS:
+ usesUefiVarsDevice = true;
+ break;
case QEMU_FIRMWARE_FEATURE_AMD_SEV:
case QEMU_FIRMWARE_FEATURE_AMD_SEV_ES:
case QEMU_FIRMWARE_FEATURE_AMD_SEV_SNP:
@@ -1574,7 +1578,6 @@ qemuFirmwareSanityCheck(const qemuFirmware *fw,
case QEMU_FIRMWARE_FEATURE_NONE:
case QEMU_FIRMWARE_FEATURE_ACPI_S3:
case QEMU_FIRMWARE_FEATURE_ACPI_S4:
- case QEMU_FIRMWARE_FEATURE_HOST_UEFI_VARS:
case QEMU_FIRMWARE_FEATURE_VERBOSE_DYNAMIC:
case QEMU_FIRMWARE_FEATURE_VERBOSE_STATIC:
case QEMU_FIRMWARE_FEATURE_LAST:
@@ -1588,14 +1591,21 @@ qemuFirmwareSanityCheck(const qemuFirmware *fw,
* support SMM. This is OK, because EFI binaries for confidential
* VMs also don't support EFI variable storage in NVRAM, instead
* the secureboot state is hardcoded to enabled.
+ *
+ * Similarly, use of the uefi-vars QEMU device guarantees that
+ * protected EFI variables work as expected without requiring SMM
+ * emulation.
*/
if (!isConfidential &&
+ !usesUefiVarsDevice &&
supportsSecureBoot != requiresSMM) {
VIR_WARN("Firmware description '%s' has invalid set of features: "
- "%s = %d, %s = %d (isConfidential = %d)",
+ "%s = %d, %s = %d, %s = %d (isConfidential = %d)",
filename,
qemuFirmwareFeatureTypeToString(QEMU_FIRMWARE_FEATURE_REQUIRES_SMM),
requiresSMM,
+ qemuFirmwareFeatureTypeToString(QEMU_FIRMWARE_FEATURE_HOST_UEFI_VARS),
+ usesUefiVarsDevice,
qemuFirmwareFeatureTypeToString(QEMU_FIRMWARE_FEATURE_SECURE_BOOT),
supportsSecureBoot,
isConfidential);
--
2.53.0

View File

@ -0,0 +1,64 @@
From 598e238bae3ca9409997f4ddf0002f7dac820e96 Mon Sep 17 00:00:00 2001
Message-ID: <598e238bae3ca9409997f4ddf0002f7dac820e96.1772815313.git.jdenemar@redhat.com>
From: Andrea Bolognani <abologna@redhat.com>
Date: Mon, 17 Nov 2025 15:47:30 +0100
Subject: [PATCH] qemu_firmware: Don't skip autoselection for ROM
It's possible to have firmware descriptors for builds intended to
be loaded as ROM, as is the case for those loaded as pflash.
There is no reason to skip firmware autoselection in those cases,
and doing so prevents useful information from being filled in.
After this change, the firmware-manual-efi-tdx test case is
augmented with some additional information. Even more information
will be filled in later, when we improve the matching logic.
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit 9a041e61ec00fa61e94858c699f00eba95b3f226)
https://issues.redhat.com/browse/RHEL-82645
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
---
src/qemu/qemu_firmware.c | 10 ++++------
.../firmware-manual-efi-tdx.x86_64-latest+inteltdx.xml | 2 +-
2 files changed, 5 insertions(+), 7 deletions(-)
diff --git a/src/qemu/qemu_firmware.c b/src/qemu/qemu_firmware.c
index 9ba5d899fa..7953b297bc 100644
--- a/src/qemu/qemu_firmware.c
+++ b/src/qemu/qemu_firmware.c
@@ -1913,13 +1913,11 @@ qemuFirmwareFillDomain(virQEMUDriver *driver,
return -1;
}
- /* If firmware autoselection is disabled and the loader is a ROM
- * instead of a PFLASH device, then we're using BIOS and we don't
- * need any information at all */
- if (!autoSelection &&
- (!loader || (loader && loader->type == VIR_DOMAIN_LOADER_TYPE_ROM))) {
+ /* If firmware autoselection is disabled and no information
+ * related to the loader was provided, then we're using the
+ * default built-in firmware and we can stop here */
+ if (!autoSelection && !loader)
return 0;
- }
/* Look for the information we need in firmware descriptors */
if ((ret = qemuFirmwareFillDomainModern(driver, def)) < 0)
diff --git a/tests/qemuxmlconfdata/firmware-manual-efi-tdx.x86_64-latest+inteltdx.xml b/tests/qemuxmlconfdata/firmware-manual-efi-tdx.x86_64-latest+inteltdx.xml
index 7428a3dfef..cdb92dcf1d 100644
--- a/tests/qemuxmlconfdata/firmware-manual-efi-tdx.x86_64-latest+inteltdx.xml
+++ b/tests/qemuxmlconfdata/firmware-manual-efi-tdx.x86_64-latest+inteltdx.xml
@@ -6,7 +6,7 @@
<vcpu placement='static'>1</vcpu>
<os>
<type arch='x86_64' machine='pc-q35-10.0'>hvm</type>
- <loader readonly='yes' type='rom'>/usr/share/edk2/ovmf/OVMF.inteltdx.secboot.fd</loader>
+ <loader readonly='yes' type='rom' format='raw'>/usr/share/edk2/ovmf/OVMF.inteltdx.secboot.fd</loader>
<boot dev='hd'/>
</os>
<features>
--
2.53.0

View File

@ -0,0 +1,44 @@
From 3273ec0979f661b5a00ce91e77c03427b5725df2 Mon Sep 17 00:00:00 2001
Message-ID: <3273ec0979f661b5a00ce91e77c03427b5725df2.1772815312.git.jdenemar@redhat.com>
From: Andrea Bolognani <abologna@redhat.com>
Date: Mon, 24 Nov 2025 17:57:25 +0100
Subject: [PATCH] qemu_firmware: Drop fallback for absent nvramTemplateFormat
If this information is missing, the parsing code will consider
the firmware descriptor to be invalid and matching against it will
not even be attempted. So we can safely drop this redundant
fallback.
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit 876a5d34d45afd71f509c971e37bdb45ceb8cc28)
https://issues.redhat.com/browse/RHEL-82645
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
---
src/qemu/qemu_firmware.c | 8 +-------
1 file changed, 1 insertion(+), 7 deletions(-)
diff --git a/src/qemu/qemu_firmware.c b/src/qemu/qemu_firmware.c
index 47a3987b64..9dff3828a2 100644
--- a/src/qemu/qemu_firmware.c
+++ b/src/qemu/qemu_firmware.c
@@ -1421,14 +1421,8 @@ qemuFirmwareEnableFeaturesModern(virDomainDef *def,
loader->nvramTemplateFormat = VIR_STORAGE_FILE_NONE;
if (!loader->nvram || virStorageSourceIsLocalStorage(loader->nvram)) {
- /* validation when parsing the JSON files ensures that we get
- * only 'raw' and 'qcow2' here. Fall back to sharing format with loader */
- if (flash->nvram_template.format)
- loader->nvramTemplateFormat = virStorageFileFormatTypeFromString(flash->nvram_template.format);
- else
- loader->nvramTemplateFormat = loader->format;
-
loader->nvramTemplate = g_strdup(flash->nvram_template.filename);
+ loader->nvramTemplateFormat = virStorageFileFormatTypeFromString(flash->nvram_template.format);
}
}
--
2.53.0

View File

@ -0,0 +1,58 @@
From ede04a5034d7b97d06033e9ccf77471afab41e04 Mon Sep 17 00:00:00 2001
Message-ID: <ede04a5034d7b97d06033e9ccf77471afab41e04.1772815312.git.jdenemar@redhat.com>
From: Andrea Bolognani <abologna@redhat.com>
Date: Sun, 28 Dec 2025 18:31:38 +0100
Subject: [PATCH] qemu_firmware: Drop 'nvram' local variable
We access the NVRAM information via the 'loader' local variable
throughout the file, and this is the only spot where the 'nvram'
local variable exists. It makes things inconsistent and opens up
the possibility of the values for 'loader' and 'nvram' going out
of sync, especially after a future commit will introduce the
need to set the former. Just get rid of the additional variable.
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit aaa0db64b4e5d44d7bb8aeee9c7b71a4f277a675)
https://issues.redhat.com/browse/RHEL-82645
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
---
src/qemu/qemu_firmware.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/src/qemu/qemu_firmware.c b/src/qemu/qemu_firmware.c
index b168ec7cf7..903b0a984d 100644
--- a/src/qemu/qemu_firmware.c
+++ b/src/qemu/qemu_firmware.c
@@ -1780,7 +1780,6 @@ qemuFirmwareFillDomain(virQEMUDriver *driver,
bool abiUpdate)
{
virDomainLoaderDef *loader = def->os.loader;
- virStorageSource *nvram = loader ? loader->nvram : NULL;
bool autoSelection = (def->os.firmware != VIR_DOMAIN_OS_DEF_FIRMWARE_NONE);
int ret;
@@ -1804,13 +1803,14 @@ qemuFirmwareFillDomain(virQEMUDriver *driver,
virStorageFileFormatTypeToString(loader->format));
return -1;
}
- if (nvram &&
- nvram->format &&
- nvram->format != VIR_STORAGE_FILE_RAW &&
- nvram->format != VIR_STORAGE_FILE_QCOW2) {
+ if (loader &&
+ loader->nvram &&
+ loader->nvram->format &&
+ loader->nvram->format != VIR_STORAGE_FILE_RAW &&
+ loader->nvram->format != VIR_STORAGE_FILE_QCOW2) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("Unsupported nvram format '%1$s'"),
- virStorageFileFormatTypeToString(nvram->format));
+ virStorageFileFormatTypeToString(loader->nvram->format));
return -1;
}
--
2.53.0

View File

@ -0,0 +1,232 @@
From 1cd291897b5a4f97d2ceaf318584760dbd410dc2 Mon Sep 17 00:00:00 2001
Message-ID: <1cd291897b5a4f97d2ceaf318584760dbd410dc2.1772815312.git.jdenemar@redhat.com>
From: Andrea Bolognani <abologna@redhat.com>
Date: Thu, 27 Nov 2025 20:14:46 +0100
Subject: [PATCH] qemu_firmware: Drop support for kernel descriptors
I have been able to find exactly zero evidence of this type of
firmware descriptor actually existing in the wild, so this is
essentialy dead code. Dropping it simplifies the task of further
tweaking the firmware selection code.
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit 3f7eea0e17a4db70820c256af9705731a9a54672)
https://issues.redhat.com/browse/RHEL-82645
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
---
src/qemu/qemu_firmware.c | 83 ++--------------------------------------
1 file changed, 3 insertions(+), 80 deletions(-)
diff --git a/src/qemu/qemu_firmware.c b/src/qemu/qemu_firmware.c
index 5bd34ea87f..b168ec7cf7 100644
--- a/src/qemu/qemu_firmware.c
+++ b/src/qemu/qemu_firmware.c
@@ -92,12 +92,6 @@ struct _qemuFirmwareMappingFlash {
};
-typedef struct _qemuFirmwareMappingKernel qemuFirmwareMappingKernel;
-struct _qemuFirmwareMappingKernel {
- char *filename;
-};
-
-
typedef struct _qemuFirmwareMappingMemory qemuFirmwareMappingMemory;
struct _qemuFirmwareMappingMemory {
char *filename;
@@ -107,7 +101,6 @@ struct _qemuFirmwareMappingMemory {
typedef enum {
QEMU_FIRMWARE_DEVICE_NONE = 0,
QEMU_FIRMWARE_DEVICE_FLASH,
- QEMU_FIRMWARE_DEVICE_KERNEL,
QEMU_FIRMWARE_DEVICE_MEMORY,
QEMU_FIRMWARE_DEVICE_LAST
@@ -118,7 +111,6 @@ VIR_ENUM_IMPL(qemuFirmwareDevice,
QEMU_FIRMWARE_DEVICE_LAST,
"",
"flash",
- "kernel",
"memory",
);
@@ -129,7 +121,6 @@ struct _qemuFirmwareMapping {
union {
qemuFirmwareMappingFlash flash;
- qemuFirmwareMappingKernel kernel;
qemuFirmwareMappingMemory memory;
} data;
};
@@ -222,13 +213,6 @@ qemuFirmwareMappingFlashFreeContent(qemuFirmwareMappingFlash *flash)
}
-static void
-qemuFirmwareMappingKernelFreeContent(qemuFirmwareMappingKernel *kernel)
-{
- g_free(kernel->filename);
-}
-
-
static void
qemuFirmwareMappingMemoryFreeContent(qemuFirmwareMappingMemory *memory)
{
@@ -243,9 +227,6 @@ qemuFirmwareMappingFreeContent(qemuFirmwareMapping *mapping)
case QEMU_FIRMWARE_DEVICE_FLASH:
qemuFirmwareMappingFlashFreeContent(&mapping->data.flash);
break;
- case QEMU_FIRMWARE_DEVICE_KERNEL:
- qemuFirmwareMappingKernelFreeContent(&mapping->data.kernel);
- break;
case QEMU_FIRMWARE_DEVICE_MEMORY:
qemuFirmwareMappingMemoryFreeContent(&mapping->data.memory);
break;
@@ -418,24 +399,6 @@ qemuFirmwareMappingFlashParse(const char *path,
}
-static int
-qemuFirmwareMappingKernelParse(const char *path,
- virJSONValue *doc,
- qemuFirmwareMappingKernel *kernel)
-{
- const char *filename;
-
- if (!(filename = virJSONValueObjectGetString(doc, "filename"))) {
- VIR_DEBUG("missing 'filename' in '%s'", path);
- return -1;
- }
-
- kernel->filename = g_strdup(filename);
-
- return 0;
-}
-
-
static int
qemuFirmwareMappingMemoryParse(const char *path,
virJSONValue *doc,
@@ -485,10 +448,6 @@ qemuFirmwareMappingParse(const char *path,
if (qemuFirmwareMappingFlashParse(path, mapping, &fw->mapping.data.flash) < 0)
return -1;
break;
- case QEMU_FIRMWARE_DEVICE_KERNEL:
- if (qemuFirmwareMappingKernelParse(path, mapping, &fw->mapping.data.kernel) < 0)
- return -1;
- break;
case QEMU_FIRMWARE_DEVICE_MEMORY:
if (qemuFirmwareMappingMemoryParse(path, mapping, &fw->mapping.data.memory) < 0)
return -1;
@@ -732,19 +691,6 @@ qemuFirmwareMappingFlashFormat(virJSONValue *mapping,
}
-static int
-qemuFirmwareMappingKernelFormat(virJSONValue *mapping,
- qemuFirmwareMappingKernel *kernel)
-{
- if (virJSONValueObjectAppendString(mapping,
- "filename",
- kernel->filename) < 0)
- return -1;
-
- return 0;
-}
-
-
static int
qemuFirmwareMappingMemoryFormat(virJSONValue *mapping,
qemuFirmwareMappingMemory *memory)
@@ -774,10 +720,6 @@ qemuFirmwareMappingFormat(virJSONValue *doc,
if (qemuFirmwareMappingFlashFormat(mapping, &fw->mapping.data.flash) < 0)
return -1;
break;
- case QEMU_FIRMWARE_DEVICE_KERNEL:
- if (qemuFirmwareMappingKernelFormat(mapping, &fw->mapping.data.kernel) < 0)
- return -1;
- break;
case QEMU_FIRMWARE_DEVICE_MEMORY:
if (qemuFirmwareMappingMemoryFormat(mapping, &fw->mapping.data.memory) < 0)
return -1;
@@ -920,21 +862,17 @@ qemuFirmwareMatchesMachineArch(const qemuFirmware *fw,
* qemuFirmwareMatchesPaths:
* @fw: firmware definition
* @loader: loader definition
- * @kernelPath: path to kernel image
*
* Checks whether @fw is compatible with the information provided as
* part of the domain definition.
*
- * Returns: true if @fw is compatible with @loader and @kernelPath,
- * false otherwise
+ * Returns: true if @fw is compatible with @loader, false otherwise
*/
static bool
qemuFirmwareMatchesPaths(const qemuFirmware *fw,
- const virDomainLoaderDef *loader,
- const char *kernelPath)
+ const virDomainLoaderDef *loader)
{
const qemuFirmwareMappingFlash *flash = &fw->mapping.data.flash;
- const qemuFirmwareMappingKernel *kernel = &fw->mapping.data.kernel;
const qemuFirmwareMappingMemory *memory = &fw->mapping.data.memory;
switch (fw->mapping.device) {
@@ -954,11 +892,6 @@ qemuFirmwareMatchesPaths(const qemuFirmware *fw,
!virFileComparePaths(loader->path, memory->filename))
return false;
break;
- case QEMU_FIRMWARE_DEVICE_KERNEL:
- if (kernelPath &&
- !virFileComparePaths(kernelPath, kernel->filename))
- return false;
- break;
case QEMU_FIRMWARE_DEVICE_NONE:
case QEMU_FIRMWARE_DEVICE_LAST:
return false;
@@ -1183,7 +1116,7 @@ qemuFirmwareMatchDomain(const virDomainDef *def,
return false;
}
- if (!qemuFirmwareMatchesPaths(fw, def->os.loader, def->os.kernel)) {
+ if (!qemuFirmwareMatchesPaths(fw, def->os.loader)) {
VIR_DEBUG("No matching path in '%s'", path);
return false;
}
@@ -1424,7 +1357,6 @@ qemuFirmwareEnableFeaturesModern(virDomainDef *def,
const qemuFirmware *fw)
{
const qemuFirmwareMappingFlash *flash = &fw->mapping.data.flash;
- const qemuFirmwareMappingKernel *kernel = &fw->mapping.data.kernel;
const qemuFirmwareMappingMemory *memory = &fw->mapping.data.memory;
virDomainLoaderDef *loader = NULL;
virStorageFileFormat format;
@@ -1482,14 +1414,6 @@ qemuFirmwareEnableFeaturesModern(virDomainDef *def,
loader->path, NULLSTR(loader->nvramTemplate));
break;
- case QEMU_FIRMWARE_DEVICE_KERNEL:
- VIR_FREE(def->os.kernel);
- def->os.kernel = g_strdup(kernel->filename);
-
- VIR_DEBUG("decided on kernel '%s'",
- def->os.kernel);
- break;
-
case QEMU_FIRMWARE_DEVICE_MEMORY:
if (!def->os.loader)
def->os.loader = virDomainLoaderDefNew();
@@ -2056,7 +1980,6 @@ qemuFirmwareGetSupported(const char *machine,
fwpath = memory->filename;
break;
- case QEMU_FIRMWARE_DEVICE_KERNEL:
case QEMU_FIRMWARE_DEVICE_NONE:
case QEMU_FIRMWARE_DEVICE_LAST:
break;
--
2.53.0

View File

@ -0,0 +1,61 @@
From 5dd010d79cb3625e01e9721cb770a7bf235b561e Mon Sep 17 00:00:00 2001
Message-ID: <5dd010d79cb3625e01e9721cb770a7bf235b561e.1772815313.git.jdenemar@redhat.com>
From: Andrea Bolognani <abologna@redhat.com>
Date: Wed, 21 Jan 2026 19:42:40 +0100
Subject: [PATCH] qemu_firmware: Fill in varstore information
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
If the matching firmware requires the use of varstore, we
have to bubble up information about it, namely the path to
the template. If the struct member doesn't exist yet, we need
to allocate it.
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
(cherry picked from commit da7eb72148ce787e719faf2ceeaa7ff3c458a50a)
https://issues.redhat.com/browse/RHEL-82645
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
---
src/qemu/qemu_firmware.c | 14 ++++++++++++--
1 file changed, 12 insertions(+), 2 deletions(-)
diff --git a/src/qemu/qemu_firmware.c b/src/qemu/qemu_firmware.c
index 60635b559f..5a07e3181f 100644
--- a/src/qemu/qemu_firmware.c
+++ b/src/qemu/qemu_firmware.c
@@ -1492,6 +1492,7 @@ qemuFirmwareEnableFeaturesModern(virDomainDef *def,
const qemuFirmwareMappingFlash *flash = &fw->mapping.data.flash;
const qemuFirmwareMappingMemory *memory = &fw->mapping.data.memory;
virDomainLoaderDef *loader = NULL;
+ virDomainVarstoreDef *varstore = NULL;
virStorageFileFormat format;
bool hasSecureBoot = false;
bool hasEnrolledKeys = false;
@@ -1552,8 +1553,17 @@ qemuFirmwareEnableFeaturesModern(virDomainDef *def,
VIR_FREE(loader->path);
loader->path = g_strdup(memory->filename);
- VIR_DEBUG("decided on loader '%s'",
- loader->path);
+ if (memory->template) {
+ if (!def->os.varstore)
+ def->os.varstore = virDomainVarstoreDefNew();
+ varstore = def->os.varstore;
+
+ VIR_FREE(varstore->template);
+ varstore->template = g_strdup(memory->template);
+ }
+
+ VIR_DEBUG("decided on loader '%s' template '%s'",
+ loader->path, NULLSTR(varstore ? varstore->template : NULL));
break;
case QEMU_FIRMWARE_DEVICE_NONE:
--
2.53.0

View File

@ -0,0 +1,86 @@
From 5f0e8ea3a876e5bd88f1312cc5ffd90469c1e190 Mon Sep 17 00:00:00 2001
Message-ID: <5f0e8ea3a876e5bd88f1312cc5ffd90469c1e190.1772815314.git.jdenemar@redhat.com>
From: Andrea Bolognani <abologna@redhat.com>
Date: Wed, 21 Jan 2026 18:25:37 +0100
Subject: [PATCH] qemu_firmware: Generate varstore path when necessary
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Introduce qemuFirmwareEnsureVarstore(), which performs the same
task as the existing qemuFirmwareEnsureNVRAM() but for the
varstore element.
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
(cherry picked from commit 0dd118cceee833ff905e6c24785a2acda8ccc80b)
https://issues.redhat.com/browse/RHEL-82645
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
---
src/qemu/qemu_firmware.c | 39 ++++++++++++++++++++++++++++++++++++---
1 file changed, 36 insertions(+), 3 deletions(-)
diff --git a/src/qemu/qemu_firmware.c b/src/qemu/qemu_firmware.c
index 5a07e3181f..d8633c6b28 100644
--- a/src/qemu/qemu_firmware.c
+++ b/src/qemu/qemu_firmware.c
@@ -1069,6 +1069,38 @@ qemuFirmwareEnsureNVRAM(virDomainDef *def,
}
+/**
+ * qemuFirmwareEnsureVarstore:
+ * @def: domain definition
+ * @driver: QEMU driver
+ *
+ * Make sure that information for the varstore is present. This might
+ * involve automatically generating the corresponding path.
+ */
+static void
+qemuFirmwareEnsureVarstore(virDomainDef *def,
+ virQEMUDriver *driver)
+{
+ g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
+ virDomainLoaderDef *loader = def->os.loader;
+ virDomainVarstoreDef *varstore = def->os.varstore;
+
+ if (!loader)
+ return;
+
+ if (loader->type != VIR_DOMAIN_LOADER_TYPE_ROM)
+ return;
+
+ if (!varstore)
+ return;
+
+ if (varstore->path)
+ return;
+
+ varstore->path = g_strdup_printf("%s/%s.json",
+ cfg->varstoreDir, def->name);
+}
+
/**
* qemuFirmwareSetOsFeatures:
@@ -2063,10 +2095,11 @@ qemuFirmwareFillDomain(virQEMUDriver *driver,
}
}
- /* Always ensure that the NVRAM path is present, even if we
- * haven't found a match: the configuration might simply be
- * referring to a custom firmware build */
+ /* Always ensure that the NVRAM/varstore is configured where
+ * appropriate, even if we haven't found a match: the configuration
+ * might simply be referring to a custom firmware build */
qemuFirmwareEnsureNVRAM(def, driver, abiUpdate);
+ qemuFirmwareEnsureVarstore(def, driver);
return 0;
}
--
2.53.0

View File

@ -0,0 +1,72 @@
From 9c29beb017582822dc341bdc34d78b4b2b95162f Mon Sep 17 00:00:00 2001
Message-ID: <9c29beb017582822dc341bdc34d78b4b2b95162f.1772815312.git.jdenemar@redhat.com>
From: Andrea Bolognani <abologna@redhat.com>
Date: Wed, 26 Nov 2025 19:01:12 +0100
Subject: [PATCH] qemu_firmware: Ignore stateless/combined when NVRAM is
configured
For combined firmware builds, the variable storage is part of the
same image as the executable code, whereas stateless builds don't
support variable storage at all.
In both cases, the use of a separate NVRAM storage area is not
supported, so if attributes connected to one are present in the
domain XML, firmware descriptors for stateless/combined builds
should be ignored.
ROM firmware builds are stateless by definition, so the same
handling applies to them as well.
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit 3463e543fec8ac7f8173f8f6712f05bc912319cd)
https://issues.redhat.com/browse/RHEL-82645
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
---
src/qemu/qemu_firmware.c | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)
diff --git a/src/qemu/qemu_firmware.c b/src/qemu/qemu_firmware.c
index a22853361b..47a3987b64 100644
--- a/src/qemu/qemu_firmware.c
+++ b/src/qemu/qemu_firmware.c
@@ -1285,6 +1285,17 @@ qemuFirmwareMatchDomain(const virDomainDef *def,
flash->nvram_template.format);
return false;
}
+ } else {
+ if (loader && loader->nvram &&
+ (loader->nvram->path || loader->nvram->format)) {
+ VIR_DEBUG("Discarding non split loader (nvram configured)");
+ return false;
+ }
+ if (loader &&
+ (loader->nvramTemplate || loader->nvramTemplateFormat)) {
+ VIR_DEBUG("Discarding non split loader (nvram template configured)");
+ return false;
+ }
}
} else if (fw->mapping.device == QEMU_FIRMWARE_DEVICE_MEMORY) {
if (loader && loader->type &&
@@ -1302,6 +1313,17 @@ qemuFirmwareMatchDomain(const virDomainDef *def,
VIR_DEBUG("Discarding readonly loader");
return false;
}
+
+ if (loader && loader->nvram &&
+ (loader->nvram->path || loader->nvram->format)) {
+ VIR_DEBUG("Discarding rom loader (nvram configured)");
+ return false;
+ }
+ if (loader &&
+ (loader->nvramTemplate || loader->nvramTemplateFormat)) {
+ VIR_DEBUG("Discarding rom loader (nvram template configured)");
+ return false;
+ }
}
if (def->sec) {
--
2.53.0

View File

@ -0,0 +1,80 @@
From 139ffa47b64ade1e88dbe17ef049bd1303305a79 Mon Sep 17 00:00:00 2001
Message-ID: <139ffa47b64ade1e88dbe17ef049bd1303305a79.1772815312.git.jdenemar@redhat.com>
From: Andrea Bolognani <abologna@redhat.com>
Date: Mon, 24 Nov 2025 18:53:14 +0100
Subject: [PATCH] qemu_firmware: Introduce qemuFirmwareFillDomainCustom()
Simple helper for the case where completely custom firmware paths
are in use. It's quite trivial right now, but it will be expanded
slightly in an upcoming commit.
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit 3acdcd2eb78a7cc8a17acc279dfbddf873dea1f8)
https://issues.redhat.com/browse/RHEL-82645
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
---
src/qemu/qemu_firmware.c | 38 ++++++++++++++++++++++++++++++--------
1 file changed, 30 insertions(+), 8 deletions(-)
diff --git a/src/qemu/qemu_firmware.c b/src/qemu/qemu_firmware.c
index 9dff3828a2..9b6c14701f 100644
--- a/src/qemu/qemu_firmware.c
+++ b/src/qemu/qemu_firmware.c
@@ -1601,6 +1601,32 @@ qemuFirmwareFetchParsedConfigs(bool privileged,
}
+/**
+ * qemuFirmwareFillDomainCustom:
+ * @def: domain definition
+ *
+ * Fill in whatever information we can when totally custom firmware
+ * paths are in use.
+ *
+ * Should only be used as a fallback in case looking at the firmware
+ * descriptors yielded no results, and neither did going through the
+ * legacy list of CODE:VARS pairs.
+ */
+static void
+qemuFirmwareFillDomainCustom(virDomainDef *def)
+{
+ virDomainLoaderDef *loader = def->os.loader;
+
+ if (!loader)
+ return;
+
+ if (!loader->format)
+ loader->format = VIR_STORAGE_FILE_RAW;
+
+ return;
+}
+
+
/**
* qemuFirmwareFillDomainLegacy:
* @driver: QEMU driver
@@ -1890,15 +1916,11 @@ qemuFirmwareFillDomain(virQEMUDriver *driver,
if ((ret = qemuFirmwareFillDomainLegacy(driver, def)) < 0)
return -1;
- /* If we've gotten this far without finding a match, it
- * means that we're dealing with a set of completely
- * custom paths. In that case, unless the user has
- * specified otherwise, we have to assume that they're in
- * raw format */
if (ret == 1) {
- if (loader && !loader->format) {
- loader->format = VIR_STORAGE_FILE_RAW;
- }
+ /* If we've gotten this far without finding a match,
+ * it means that we're dealing with a set of completely
+ * custom paths. We can still fill in some information */
+ qemuFirmwareFillDomainCustom(def);
}
} else {
virReportError(VIR_ERR_OPERATION_FAILED,
--
2.53.0

View File

@ -0,0 +1,90 @@
From 66c0e4b7a9b472c539701bede38cbe9278fec830 Mon Sep 17 00:00:00 2001
Message-ID: <66c0e4b7a9b472c539701bede38cbe9278fec830.1772815312.git.jdenemar@redhat.com>
From: Andrea Bolognani <abologna@redhat.com>
Date: Thu, 27 Nov 2025 19:05:17 +0100
Subject: [PATCH] qemu_firmware: Move copying of nvram.format to loader.format
As explained in the comment that comes along with it, this code
ensures that the user's preference is taken into account when
nvram.format is the only information that's provided. Currently
it lives in the parser, but it makes more sense for it to be
together with the rest of the firmware selection code instead.
Note that this move is not completely seamless: once the code
is moved outside of the parser, it can no longer reliably know
whether the <loader> element actually existed in the domain
XML. The difference is subtle enough that the test suite is
completely unaffected, and we are going to rework the handling
of this scenario in a way that restores the original behavior
later anyway, so it ultimately doesn't matter.
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit 4df091dea4a41767561bab1bcd28c3fd9ac2dcea)
https://issues.redhat.com/browse/RHEL-82645
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
---
src/conf/domain_conf.c | 18 +-----------------
src/qemu/qemu_firmware.c | 15 +++++++++++++++
2 files changed, 16 insertions(+), 17 deletions(-)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index cb047e5a3e..e72cda0048 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -17937,24 +17937,8 @@ virDomainLoaderDefParseXMLLoader(virDomainLoaderDef *loader,
{
unsigned int format = 0;
- if (!loaderNode) {
- /* If there is no <loader> element but the <nvram> element
- * was present, copy the format from the latter to the
- * former.
- *
- * This ensures that a configuration such as
- *
- * <os>
- * <nvram format='foo'/>
- * </os>
- *
- * behaves as expected, that is, results in a firmware build
- * with format 'foo' being selected */
- if (loader->nvram)
- loader->format = loader->nvram->format;
-
+ if (!loaderNode)
return 0;
- }
if (virXMLPropTristateBool(loaderNode, "readonly", VIR_XML_PROP_NONE,
&loader->readonly) < 0)
diff --git a/src/qemu/qemu_firmware.c b/src/qemu/qemu_firmware.c
index 6c609ece6a..a22853361b 100644
--- a/src/qemu/qemu_firmware.c
+++ b/src/qemu/qemu_firmware.c
@@ -1783,6 +1783,21 @@ qemuFirmwareFillDomain(virQEMUDriver *driver,
bool autoSelection = (def->os.firmware != VIR_DOMAIN_OS_DEF_FIRMWARE_NONE);
int ret;
+ /* If there is no <loader> element but the <nvram> element
+ * was present, copy the format from the latter to the
+ * former.
+ *
+ * This ensures that a configuration such as
+ *
+ * <os>
+ * <nvram format='foo'/>
+ * </os>
+ *
+ * behaves as expected, that is, results in a firmware build
+ * with format 'foo' being selected */
+ if (loader && loader->nvram && !loader->format)
+ loader->format = loader->nvram->format;
+
/* If we're loading an existing configuration from disk, we
* should try as hard as possible to preserve historical
* behavior. In particular, firmware autoselection being enabled
--
2.53.0

View File

@ -0,0 +1,86 @@
From 053f28978ec5f7b3648ccb9b0b7af16b17a4c87a Mon Sep 17 00:00:00 2001
Message-ID: <053f28978ec5f7b3648ccb9b0b7af16b17a4c87a.1772815312.git.jdenemar@redhat.com>
From: Andrea Bolognani <abologna@redhat.com>
Date: Thu, 27 Nov 2025 18:25:07 +0100
Subject: [PATCH] qemu_firmware: Move format=raw compat exception
We currently apply this exception, which is critical to ensure
that the correct firmware is selected when working with older VMs,
in the postparse callback.
Move it to the firmware selection process instead, where it should
have been added in the first place.
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit 5b374c5e3fe621126327aad4398f48da288ba521)
https://issues.redhat.com/browse/RHEL-82645
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
---
src/qemu/qemu_firmware.c | 20 ++++++++++++++++++++
src/qemu/qemu_postparse.c | 17 -----------------
2 files changed, 20 insertions(+), 17 deletions(-)
diff --git a/src/qemu/qemu_firmware.c b/src/qemu/qemu_firmware.c
index 903b0a984d..6c609ece6a 100644
--- a/src/qemu/qemu_firmware.c
+++ b/src/qemu/qemu_firmware.c
@@ -1783,6 +1783,26 @@ qemuFirmwareFillDomain(virQEMUDriver *driver,
bool autoSelection = (def->os.firmware != VIR_DOMAIN_OS_DEF_FIRMWARE_NONE);
int ret;
+ /* If we're loading an existing configuration from disk, we
+ * should try as hard as possible to preserve historical
+ * behavior. In particular, firmware autoselection being enabled
+ * could never have resulted, before libvirt 9.2.0, in anything
+ * but a raw firmware image being selected.
+ *
+ * In order to ensure that existing domains keep working even if
+ * a firmware descriptor for a build with a different format is
+ * given higher priority, explicitly add this requirement to the
+ * definition before performing firmware selection */
+ if (!abiUpdate && autoSelection) {
+ if (!loader) {
+ def->os.loader = virDomainLoaderDefNew();
+ loader = def->os.loader;
+ }
+ if (!loader->format) {
+ loader->format = VIR_STORAGE_FILE_RAW;
+ }
+ }
+
/* Start by performing a thorough validation of the input.
*
* We need to do this here because the firmware selection logic
diff --git a/src/qemu/qemu_postparse.c b/src/qemu/qemu_postparse.c
index 840d6a1174..8940cb09b3 100644
--- a/src/qemu/qemu_postparse.c
+++ b/src/qemu/qemu_postparse.c
@@ -1051,23 +1051,6 @@ qemuDomainDefBootPostParse(virDomainDef *def,
{
bool abiUpdate = !!(parseFlags & VIR_DOMAIN_DEF_PARSE_ABI_UPDATE);
- /* If we're loading an existing configuration from disk, we
- * should try as hard as possible to preserve historical
- * behavior. In particular, firmware autoselection being enabled
- * could never have resulted, before libvirt 9.2.0, in anything
- * but a raw firmware image being selected.
- *
- * In order to ensure that existing domains keep working even if
- * a firmware descriptor for a build with a different format is
- * given higher priority, explicitly add this requirement to the
- * definition before performing firmware selection */
- if (!abiUpdate && def->os.firmware) {
- if (!def->os.loader)
- def->os.loader = virDomainLoaderDefNew();
- if (!def->os.loader->format)
- def->os.loader->format = VIR_STORAGE_FILE_RAW;
- }
-
/* Firmware selection can fail for a number of reasons, but the
* most likely one is that the requested configuration contains
* mistakes or includes constraints that are impossible to
--
2.53.0

View File

@ -0,0 +1,45 @@
From 9298881a07f0e25ec594d4157421eb61c9014c85 Mon Sep 17 00:00:00 2001
Message-ID: <9298881a07f0e25ec594d4157421eb61c9014c85.1772815313.git.jdenemar@redhat.com>
From: Andrea Bolognani <abologna@redhat.com>
Date: Tue, 3 Feb 2026 16:05:05 +0100
Subject: [PATCH] qemu_firmware: Only set format for custom loader if path is
present
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
We only set the template format if the template path is present,
and we should be consistent with that. The format on its own is
not very interesting anyway.
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
(cherry picked from commit 375c82a0f8e61f3762f0a7ffa26624f841a79d76)
https://issues.redhat.com/browse/RHEL-82645
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
---
src/qemu/qemu_firmware.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/src/qemu/qemu_firmware.c b/src/qemu/qemu_firmware.c
index 436b06c388..519828f6f9 100644
--- a/src/qemu/qemu_firmware.c
+++ b/src/qemu/qemu_firmware.c
@@ -1662,8 +1662,10 @@ qemuFirmwareFillDomainCustom(virDomainDef *def)
if (!loader)
return;
- if (!loader->format)
+ if (loader->path &&
+ !loader->format) {
loader->format = VIR_STORAGE_FILE_RAW;
+ }
if (loader->nvramTemplate &&
!loader->nvramTemplateFormat) {
--
2.53.0

View File

@ -0,0 +1,80 @@
From eb8df5502f4a047e93faa872047b56f047e055a4 Mon Sep 17 00:00:00 2001
Message-ID: <eb8df5502f4a047e93faa872047b56f047e055a4.1772815313.git.jdenemar@redhat.com>
From: Andrea Bolognani <abologna@redhat.com>
Date: Mon, 24 Nov 2025 14:14:36 +0100
Subject: [PATCH] qemu_firmware: Parse host-uefi-vars firmware feature
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
When present in a firmware descriptor, this feature indicates that
the corresponding executable expects to access variable storage
through the uefi-vars QEMU device.
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
(cherry picked from commit 83679d7338869aaf19b59077164cd2da391c2283)
https://issues.redhat.com/browse/RHEL-82645
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
---
src/qemu/qemu_firmware.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/src/qemu/qemu_firmware.c b/src/qemu/qemu_firmware.c
index 6a074055ca..8b9b0d91ff 100644
--- a/src/qemu/qemu_firmware.c
+++ b/src/qemu/qemu_firmware.c
@@ -145,6 +145,7 @@ typedef enum {
QEMU_FIRMWARE_FEATURE_ENROLLED_KEYS,
QEMU_FIRMWARE_FEATURE_REQUIRES_SMM,
QEMU_FIRMWARE_FEATURE_SECURE_BOOT,
+ QEMU_FIRMWARE_FEATURE_HOST_UEFI_VARS,
QEMU_FIRMWARE_FEATURE_VERBOSE_DYNAMIC,
QEMU_FIRMWARE_FEATURE_VERBOSE_STATIC,
@@ -164,6 +165,7 @@ VIR_ENUM_IMPL(qemuFirmwareFeature,
"enrolled-keys",
"requires-smm",
"secure-boot",
+ "host-uefi-vars",
"verbose-dynamic",
"verbose-static"
);
@@ -1181,6 +1183,7 @@ qemuFirmwareMatchDomain(const virDomainDef *def,
hasEnrolledKeys = true;
break;
+ case QEMU_FIRMWARE_FEATURE_HOST_UEFI_VARS:
case QEMU_FIRMWARE_FEATURE_VERBOSE_DYNAMIC:
case QEMU_FIRMWARE_FEATURE_VERBOSE_STATIC:
case QEMU_FIRMWARE_FEATURE_NONE:
@@ -1515,6 +1518,7 @@ qemuFirmwareEnableFeaturesModern(virDomainDef *def,
case QEMU_FIRMWARE_FEATURE_AMD_SEV_ES:
case QEMU_FIRMWARE_FEATURE_AMD_SEV_SNP:
case QEMU_FIRMWARE_FEATURE_INTEL_TDX:
+ case QEMU_FIRMWARE_FEATURE_HOST_UEFI_VARS:
case QEMU_FIRMWARE_FEATURE_VERBOSE_DYNAMIC:
case QEMU_FIRMWARE_FEATURE_VERBOSE_STATIC:
case QEMU_FIRMWARE_FEATURE_NONE:
@@ -1570,6 +1574,7 @@ qemuFirmwareSanityCheck(const qemuFirmware *fw,
case QEMU_FIRMWARE_FEATURE_NONE:
case QEMU_FIRMWARE_FEATURE_ACPI_S3:
case QEMU_FIRMWARE_FEATURE_ACPI_S4:
+ case QEMU_FIRMWARE_FEATURE_HOST_UEFI_VARS:
case QEMU_FIRMWARE_FEATURE_VERBOSE_DYNAMIC:
case QEMU_FIRMWARE_FEATURE_VERBOSE_STATIC:
case QEMU_FIRMWARE_FEATURE_LAST:
@@ -2084,6 +2089,7 @@ qemuFirmwareGetSupported(const char *machine,
case QEMU_FIRMWARE_FEATURE_AMD_SEV_ES:
case QEMU_FIRMWARE_FEATURE_AMD_SEV_SNP:
case QEMU_FIRMWARE_FEATURE_INTEL_TDX:
+ case QEMU_FIRMWARE_FEATURE_HOST_UEFI_VARS:
case QEMU_FIRMWARE_FEATURE_VERBOSE_DYNAMIC:
case QEMU_FIRMWARE_FEATURE_VERBOSE_STATIC:
case QEMU_FIRMWARE_FEATURE_LAST:
--
2.53.0

View File

@ -0,0 +1,39 @@
From 8c34553e1e77dcea4f86ee2c2668de251876b42e Mon Sep 17 00:00:00 2001
Message-ID: <8c34553e1e77dcea4f86ee2c2668de251876b42e.1772815313.git.jdenemar@redhat.com>
From: Andrea Bolognani <abologna@redhat.com>
Date: Fri, 28 Nov 2025 17:00:09 +0100
Subject: [PATCH] qemu_firmware: Prefer template format to loader format
In the vast majority of cases they will match, but it just makes
more logical sense to copy the format from the NVRAM template to
the NVRAM file itself.
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit a92c1409568ac70bfa0a29099181452ef625d937)
https://issues.redhat.com/browse/RHEL-82645
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
---
src/qemu/qemu_firmware.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/src/qemu/qemu_firmware.c b/src/qemu/qemu_firmware.c
index f32e46cc8c..b08fb95585 100644
--- a/src/qemu/qemu_firmware.c
+++ b/src/qemu/qemu_firmware.c
@@ -991,7 +991,10 @@ qemuFirmwareEnsureNVRAM(virDomainDef *def,
* NVRAM format if that's missing though */
if (!virStorageSourceIsEmpty(loader->nvram)) {
if (!loader->nvram->format) {
- loader->nvram->format = loader->format;
+ if (loader->nvramTemplateFormat)
+ loader->nvram->format = loader->nvramTemplateFormat;
+ else
+ loader->nvram->format = loader->format;
}
return;
}
--
2.53.0

View File

@ -0,0 +1,33 @@
From 4b9e4bf49a5891cae82bfbc4476b4046c8ee362d Mon Sep 17 00:00:00 2001
Message-ID: <4b9e4bf49a5891cae82bfbc4476b4046c8ee362d.1772815313.git.jdenemar@redhat.com>
From: Andrea Bolognani <abologna@redhat.com>
Date: Mon, 17 Nov 2025 20:17:45 +0100
Subject: [PATCH] qemu_firmware: ROM firmware is always in raw format
By definition.
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit 1b78d647da26b101267eb86401ad0a7d722a773d)
https://issues.redhat.com/browse/RHEL-82645
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
---
src/qemu/qemu_firmware.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/qemu/qemu_firmware.c b/src/qemu/qemu_firmware.c
index 70ac88c373..9ba5d899fa 100644
--- a/src/qemu/qemu_firmware.c
+++ b/src/qemu/qemu_firmware.c
@@ -1470,6 +1470,7 @@ qemuFirmwareEnableFeaturesModern(virDomainDef *def,
loader = def->os.loader;
loader->type = VIR_DOMAIN_LOADER_TYPE_ROM;
+ loader->format = VIR_STORAGE_FILE_RAW;
VIR_FREE(loader->path);
loader->path = g_strdup(memory->filename);
--
2.53.0

View File

@ -0,0 +1,53 @@
From d03ee871a69a16ff2975e925150fa361a5b283b4 Mon Sep 17 00:00:00 2001
Message-ID: <d03ee871a69a16ff2975e925150fa361a5b283b4.1772815313.git.jdenemar@redhat.com>
From: Andrea Bolognani <abologna@redhat.com>
Date: Wed, 17 Dec 2025 01:12:35 +0100
Subject: [PATCH] qemu_firmware: Refactor setting NVRAM format
Instead of setting the format every single time, knowing that we
might throw away the entire definition immediately afterwards,
and duplicating a check, only set it if we are going to perform
an early return due to the rest of the definition being properly
filled in already.
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit ab8efe6fd076d5e944902e4b2194a7db35a85101)
https://issues.redhat.com/browse/RHEL-82645
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
---
src/qemu/qemu_firmware.c | 15 ++++++++-------
1 file changed, 8 insertions(+), 7 deletions(-)
diff --git a/src/qemu/qemu_firmware.c b/src/qemu/qemu_firmware.c
index a7bb8f7e45..f32e46cc8c 100644
--- a/src/qemu/qemu_firmware.c
+++ b/src/qemu/qemu_firmware.c
@@ -985,15 +985,16 @@ qemuFirmwareEnsureNVRAM(virDomainDef *def,
if (loader->stateless == VIR_TRISTATE_BOOL_YES)
return;
- /* If the NVRAM format hasn't been set yet, inherit the same as
- * the loader */
- if (loader->nvram && !loader->nvram->format)
- loader->nvram->format = loader->format;
-
if (loader->nvram) {
- /* Nothing to do if a proper NVRAM backend is already configured */
- if (!virStorageSourceIsEmpty(loader->nvram))
+ /* If a proper NVRAM backend is already configured, we are
+ * done for the most part. We might still need to set the
+ * NVRAM format if that's missing though */
+ if (!virStorageSourceIsEmpty(loader->nvram)) {
+ if (!loader->nvram->format) {
+ loader->nvram->format = loader->format;
+ }
return;
+ }
/* otherwise we want to reset and re-populate the definition */
virObjectUnref(loader->nvram);
--
2.53.0

Some files were not shown because too many files have changed in this diff Show More