libvirt-11.10.0-10.el10

- qemu: Introduce QEMU_CAPS_OBJECT_IOMMUFD (RHEL-150351)
- qemu: Move IOMMUFD validation to qemu_validate (RHEL-150351)
- util: Move openning IOMMU device to viriommufd (RHEL-150351)
- qemu_process: Refactor qemuProcessOpenIommuFd (RHEL-150351)
- util: Move openning VFIO device to virpci (RHEL-150351)
- qemu_process: Refactor qemuProcessOpenVfioDeviceFd (RHEL-150351)
- util: Use virPCIDevice as argument in virPCIDeviceGetVfioPath (RHEL-150351)
- conf: Introduce virHostdevIsPCIDeviceWithIOMMUFD (RHEL-150351)
- conf: Introduce virDomainDefHasPCIHostdevWithIOMMUFD (RHEL-150351)
- qemu_domain: Add missing IOMMUFD cleanup (RHEL-150351)
- qemu_process: Fix FD leak with multiple host devices using IOMMUFD (RHEL-150351)
- qemu_process: Refactor qemuProcessOpenVfioFds (RHEL-150351)
- qemuxmlconftest: Refactor host device preparation (RHEL-150351)
- qemuxmlconftest: Rename and refactor testSetupHostdevPrivateData (RHEL-150351)
- qemuxmlconftest: Set fake FD for IOMMUFD (RHEL-150351)
- qemu: Convert IOMMUFD to qemuFDPassDirect (RHEL-150351)
- qemu: Convert vfioDeviceFd to qemuFDPassDirect (RHEL-150351)
- qemu_command: Don't use host property if IOMMUFD is used (RHEL-150351)
- qemu: Save IOMMUFD state into status XML (RHEL-150351)
- qemu_hotplug: Remove iommufd object if no longer needed (RHEL-150351)
- qemu_command: Extract building IOMMUFD props to function (RHEL-150351)
- qemu_hotplug: Add support to hotplug host device with IOMMUFD (RHEL-150351)
- conf: Introduce iommufd enum for domaincaps (RHEL-148135)
- qemu: Fill iommufd domain capability (RHEL-148135)
- tests: properly mock VFIO and IOMMU checks (RHEL-148135)
- iommufd: fix FD leak in case of error (RHEL-150351)

Resolves: RHEL-148135, RHEL-150351
This commit is contained in:
Jiri Denemark 2026-02-18 15:07:39 +01:00
parent e043cfc857
commit 481c875102
27 changed files with 3807 additions and 1 deletions

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,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

File diff suppressed because it is too large Load Diff

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,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,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,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

@ -0,0 +1,134 @@
From 598a0e9ee5f59faea21f03ccb02d0830e73f975f Mon Sep 17 00:00:00 2001
Message-ID: <598a0e9ee5f59faea21f03ccb02d0830e73f975f.1771423659.git.jdenemar@redhat.com>
From: Pavel Hrdina <phrdina@redhat.com>
Date: Sun, 15 Feb 2026 21:21:53 +0100
Subject: [PATCH] qemu_hotplug: Add support to hotplug host device with IOMMUFD
For first host device we need to add iommufd object as well.
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit 5d16bef1a69500791be454239e3b9ac68ec53ace)
Resolves: https://issues.redhat.com/browse/RHEL-150351
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
---
src/qemu/qemu_hotplug.c | 39 +++++++++++++++++++++++++++++++++++++++
src/qemu/qemu_process.c | 4 ++--
src/qemu/qemu_process.h | 3 +++
3 files changed, 44 insertions(+), 2 deletions(-)
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index 10ad13a416..a455c2cd53 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -1561,13 +1561,16 @@ qemuDomainAttachHostPCIDevice(virQEMUDriver *driver,
virDomainDeviceDef dev = { VIR_DOMAIN_DEVICE_HOSTDEV,
{ .hostdev = hostdev } };
virDomainDeviceInfo *info = hostdev->info;
+ qemuDomainHostdevPrivate *hostdevPriv = QEMU_DOMAIN_HOSTDEV_PRIVATE(hostdev);
int ret;
g_autoptr(virJSONValue) devprops = NULL;
+ g_autoptr(virJSONValue) objprops = NULL;
bool releaseaddr = false;
bool teardowncgroup = false;
bool teardownlabel = false;
bool teardowndevice = false;
bool teardownmemlock = false;
+ bool removeiommufd = false;
g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
unsigned int flags = 0;
@@ -1617,11 +1620,38 @@ qemuDomainAttachHostPCIDevice(virQEMUDriver *driver,
goto error;
}
+ if (virHostdevIsPCIDeviceWithIOMMUFD(hostdev)) {
+ if (qemuProcessOpenVfioDeviceFd(hostdev) < 0)
+ goto error;
+
+ if (!priv->iommufdState) {
+ if (qemuProcessOpenIommuFd(vm) < 0)
+ goto error;
+
+ if (!(objprops = qemuBuildIOMMUFDProps(priv->iommufd)))
+ goto error;
+ }
+ }
+
if (!(devprops = qemuBuildPCIHostdevDevProps(vm->def, hostdev)))
goto error;
qemuDomainObjEnterMonitor(vm);
+ if (objprops) {
+ if ((ret = qemuFDPassDirectTransferMonitor(priv->iommufd, priv->mon)) < 0)
+ goto exit_monitor;
+
+ if ((ret = qemuMonitorAddObject(priv->mon, &objprops, NULL)) < 0)
+ goto exit_monitor;
+
+ priv->iommufdState = true;
+ removeiommufd = true;
+ }
+
+ if ((ret = qemuFDPassDirectTransferMonitor(hostdevPriv->vfioDeviceFd, priv->mon)) < 0)
+ goto exit_monitor;
+
if ((ret = qemuDomainAttachExtensionDevice(priv->mon, hostdev->info)) < 0)
goto exit_monitor;
@@ -1652,6 +1682,15 @@ qemuDomainAttachHostPCIDevice(virQEMUDriver *driver,
if (teardownmemlock && qemuDomainAdjustMaxMemLock(vm) < 0)
VIR_WARN("Unable to reset maximum locked memory on hotplug fail");
+ if (removeiommufd) {
+ qemuDomainObjEnterMonitor(vm);
+ ignore_value(qemuMonitorDelObject(priv->mon, "iommufd0", false));
+ qemuDomainObjExitMonitor(vm);
+ }
+
+ qemuFDPassDirectTransferMonitorRollback(hostdevPriv->vfioDeviceFd, priv->mon);
+ qemuFDPassDirectTransferMonitorRollback(priv->iommufd, priv->mon);
+
if (releaseaddr)
qemuDomainReleaseDeviceAddress(vm, info);
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 59fff1aa19..1aff3a277b 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -7681,7 +7681,7 @@ qemuProcessPrepareHostBackendChardevHotplug(virDomainObj *vm,
*
* Returns: 0 on success, -1 on failure
*/
-static int
+int
qemuProcessOpenIommuFd(virDomainObj *vm)
{
qemuDomainObjPrivate *priv = vm->privateData;
@@ -7705,7 +7705,7 @@ qemuProcessOpenIommuFd(virDomainObj *vm)
*
* Returns: 0 on success, -1 on failure
*/
-static int
+int
qemuProcessOpenVfioDeviceFd(virDomainHostdevDef *hostdev)
{
qemuDomainHostdevPrivate *hostdevPriv = QEMU_DOMAIN_HOSTDEV_PRIVATE(hostdev);
diff --git a/src/qemu/qemu_process.h b/src/qemu/qemu_process.h
index df78b00abb..1023b7cb25 100644
--- a/src/qemu/qemu_process.h
+++ b/src/qemu/qemu_process.h
@@ -134,6 +134,9 @@ int qemuProcessPrepareHostBackendChardevHotplug(virDomainObj *vm,
virDomainDeviceDef *dev)
ATTRIBUTE_MOCKABLE;
+int qemuProcessOpenIommuFd(virDomainObj *vm);
+
+int qemuProcessOpenVfioDeviceFd(virDomainHostdevDef *hostdev);
int qemuProcessPrepareHost(virQEMUDriver *driver,
virDomainObj *vm,
--
2.53.0

View File

@ -0,0 +1,40 @@
From 2274a02bd1b2cefb48d7d66fe8db10e5c9cd853d Mon Sep 17 00:00:00 2001
Message-ID: <2274a02bd1b2cefb48d7d66fe8db10e5c9cd853d.1771423659.git.jdenemar@redhat.com>
From: Pavel Hrdina <phrdina@redhat.com>
Date: Sun, 15 Feb 2026 19:57:12 +0100
Subject: [PATCH] qemu_hotplug: Remove iommufd object if no longer needed
When removing last host device using IOMMUFD remove the iommufd object
as well.
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit 300ebf01b88d154312c1a5a684be2add95dd7f31)
Resolves: https://issues.redhat.com/browse/RHEL-150351
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
---
src/qemu/qemu_hotplug.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index 9445599d2c..10ad13a416 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -4986,6 +4986,14 @@ qemuDomainRemoveHostDevice(virQEMUDriver *driver,
}
}
+ if (priv->iommufdState &&
+ !virDomainDefHasPCIHostdevWithIOMMUFD(vm->def)) {
+ qemuDomainObjEnterMonitor(vm);
+ ignore_value(qemuMonitorDelObject(priv->mon, "iommufd0", false));
+ qemuDomainObjExitMonitor(vm);
+ priv->iommufdState = false;
+ }
+
virDomainAuditHostdev(vm, hostdev, "detach", true);
if (!virHostdevIsPCIDevice(hostdev) &&
--
2.53.0

View File

@ -0,0 +1,48 @@
From e42d8373633488a6d67b6c895953de183b1dd495 Mon Sep 17 00:00:00 2001
Message-ID: <e42d8373633488a6d67b6c895953de183b1dd495.1771423659.git.jdenemar@redhat.com>
From: Pavel Hrdina <phrdina@redhat.com>
Date: Sun, 15 Feb 2026 19:13:19 +0100
Subject: [PATCH] qemu_process: Fix FD leak with multiple host devices using
IOMMUFD
We would open IOMMU device for each host device with IOMMUFD backend
leaking FD except for the last one. Since we are adding only single
iommufd object we need to open it only once.
Fixes: 2f0999a161910e3992458902ce90d37f8b8f2642
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit d194f362f342c22731670e365e8a2681759dbc57)
Resolves: https://issues.redhat.com/browse/RHEL-150351
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
---
src/qemu/qemu_process.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 3bd81c55b3..da7a9fc11f 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -7736,13 +7736,15 @@ qemuProcessOpenVfioFds(virDomainObj *vm)
/* Open VFIO device FD */
if (qemuProcessOpenVfioDeviceFd(hostdev) < 0)
return -1;
-
- /* Open IOMMU FD */
- if (qemuProcessOpenIommuFd(vm) < 0)
- return -1;
}
}
+ /* Open IOMMU FD */
+ if (virDomainDefHasPCIHostdevWithIOMMUFD(vm->def) &&
+ qemuProcessOpenIommuFd(vm) < 0) {
+ return -1;
+ }
+
return 0;
}
--
2.53.0

View File

@ -0,0 +1,72 @@
From da301bafb4eb4658a0b4aae8d8b633bc9a1ef2f9 Mon Sep 17 00:00:00 2001
Message-ID: <da301bafb4eb4658a0b4aae8d8b633bc9a1ef2f9.1771423658.git.jdenemar@redhat.com>
From: Pavel Hrdina <phrdina@redhat.com>
Date: Sun, 15 Feb 2026 19:01:35 +0100
Subject: [PATCH] qemu_process: Refactor qemuProcessOpenIommuFd
This will allow us reusing same code for hotplug.
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit ff2848827f42578115ef54a389a41798a96fd338)
Resolves: https://issues.redhat.com/browse/RHEL-150351
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
---
src/qemu/qemu_process.c | 15 ++++++---------
1 file changed, 6 insertions(+), 9 deletions(-)
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index dd165512f3..71770d2099 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -7676,24 +7676,23 @@ qemuProcessPrepareHostBackendChardevHotplug(virDomainObj *vm,
/**
* qemuProcessOpenIommuFd:
* @vm: domain object
- * @iommuFd: returned file descriptor
*
* Opens /dev/iommu file descriptor for the VM.
*
- * Returns: FD on success, -1 on failure
+ * Returns: 0 on success, -1 on failure
*/
static int
qemuProcessOpenIommuFd(virDomainObj *vm)
{
- int fd = -1;
+ qemuDomainObjPrivate *priv = vm->privateData;
VIR_DEBUG("Opening IOMMU FD for domain %s", vm->def->name);
- if ((fd = virIOMMUFDOpenDevice()) < 0)
+ if ((priv->iommufd = virIOMMUFDOpenDevice()) < 0)
return -1;
- VIR_DEBUG("Opened IOMMU FD %d for domain %s", fd, vm->def->name);
- return fd;
+ VIR_DEBUG("Opened IOMMU FD %d for domain %s", priv->iommufd, vm->def->name);
+ return 0;
}
/**
@@ -7750,7 +7749,6 @@ 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 */
@@ -7768,8 +7766,7 @@ qemuProcessOpenVfioFds(virDomainObj *vm)
return -1;
/* Open IOMMU FD */
- priv->iommufd = qemuProcessOpenIommuFd(vm);
- if (priv->iommufd == -1)
+ if (qemuProcessOpenIommuFd(vm) < 0)
return -1;
}
}
--
2.53.0

View File

@ -0,0 +1,75 @@
From 24f32b0d564d4c782b4a39990ef6508d9260774a Mon Sep 17 00:00:00 2001
Message-ID: <24f32b0d564d4c782b4a39990ef6508d9260774a.1771423658.git.jdenemar@redhat.com>
From: Pavel Hrdina <phrdina@redhat.com>
Date: Sun, 15 Feb 2026 19:09:23 +0100
Subject: [PATCH] qemu_process: Refactor qemuProcessOpenVfioDeviceFd
This will allow us reusing same code for hotplug support.
As part of refactor remove redundant checks.
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit 76b720168bee49497519bbca2147cbd65ae7fcbf)
Resolves: https://issues.redhat.com/browse/RHEL-150351
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
---
src/qemu/qemu_process.c | 22 +++++++++-------------
1 file changed, 9 insertions(+), 13 deletions(-)
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 55cd930df8..7e32325fa0 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -7698,23 +7698,21 @@ qemuProcessOpenIommuFd(virDomainObj *vm)
/**
* 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
+ * Returns: 0 on success, -1 on failure
*/
static int
qemuProcessOpenVfioDeviceFd(virDomainHostdevDef *hostdev)
{
- 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;
- }
+ qemuDomainHostdevPrivate *hostdevPriv = QEMU_DOMAIN_HOSTDEV_PRIVATE(hostdev);
+ virDomainHostdevSubsysPCI *pci = &hostdev->source.subsys.u.pci;
- return virPCIDeviceOpenVfioFd(&hostdev->source.subsys.u.pci.addr);
+ if ((hostdevPriv->vfioDeviceFd = virPCIDeviceOpenVfioFd(&pci->addr)) < 0)
+ return -1;
+
+ return 0;
}
/**
@@ -7733,16 +7731,14 @@ qemuProcessOpenVfioFds(virDomainObj *vm)
/* 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;
+ if (qemuProcessOpenVfioDeviceFd(hostdev) < 0)
+ return -1;
/* Open IOMMU FD */
if (qemuProcessOpenIommuFd(vm) < 0)
--
2.53.0

View File

@ -0,0 +1,77 @@
From a3696f1e0ba8ddf997e54fccd945593272635762 Mon Sep 17 00:00:00 2001
Message-ID: <a3696f1e0ba8ddf997e54fccd945593272635762.1771423659.git.jdenemar@redhat.com>
From: Pavel Hrdina <phrdina@redhat.com>
Date: Sun, 15 Feb 2026 19:15:52 +0100
Subject: [PATCH] qemu_process: Refactor qemuProcessOpenVfioFds
Follow our switch pattern to simplify the code logic
and rename the function to follow our naming pattern.
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit c83b4f367f23868793fc6b071771d0e641b7a546)
Resolves: https://issues.redhat.com/browse/RHEL-150351
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
---
src/qemu/qemu_process.c | 31 ++++++++++++++++---------------
1 file changed, 16 insertions(+), 15 deletions(-)
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index da7a9fc11f..3729edcd7e 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -7715,27 +7715,28 @@ qemuProcessOpenVfioDeviceFd(virDomainHostdevDef *hostdev)
return 0;
}
-/**
- * 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)
+qemuProcessPrepareHostHostdev(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];
- if (virHostdevIsPCIDeviceWithIOMMUFD(hostdev)) {
- /* Open VFIO device FD */
- if (qemuProcessOpenVfioDeviceFd(hostdev) < 0)
- return -1;
+ switch (hostdev->source.subsys.type) {
+ case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI:
+ if (virHostdevIsPCIDeviceWithIOMMUFD(hostdev)) {
+ /* Open VFIO device FD */
+ if (qemuProcessOpenVfioDeviceFd(hostdev) < 0)
+ return -1;
+ }
+ break;
+ case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB:
+ case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI:
+ case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST:
+ case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_MDEV:
+ case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST:
+ break;
}
}
@@ -7803,7 +7804,7 @@ qemuProcessPrepareHost(virQEMUDriver *driver,
hostdev_flags |= VIR_HOSTDEV_COLD_BOOT;
if (qemuHostdevPrepareDomainDevices(driver, vm->def, hostdev_flags) < 0)
return -1;
- if (qemuProcessOpenVfioFds(vm) < 0)
+ if (qemuProcessPrepareHostHostdev(vm) < 0)
return -1;
VIR_DEBUG("Preparing chr device backends");
--
2.53.0

View File

@ -0,0 +1,101 @@
From d851b46d3794d4ad2d0f9b74c0e0cf1a10d06682 Mon Sep 17 00:00:00 2001
Message-ID: <d851b46d3794d4ad2d0f9b74c0e0cf1a10d06682.1771423659.git.jdenemar@redhat.com>
From: Pavel Hrdina <phrdina@redhat.com>
Date: Sat, 14 Feb 2026 11:39:19 +0100
Subject: [PATCH] qemuxmlconftest: Refactor host device preparation
Create a single place for host device preparation code.
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit cb23831c020a5fab33be417426b2746a73ecdd10)
Conflicts:
- missing upstream commit b97afe28f54dae1d122baa33d1a371b68775b7b2
tests/qemuxmlconftest.c
Resolves: https://issues.redhat.com/browse/RHEL-150351
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
---
tests/qemuxmlconftest.c | 59 ++++++++++++++++++++++++++++++-----------
1 file changed, 43 insertions(+), 16 deletions(-)
diff --git a/tests/qemuxmlconftest.c b/tests/qemuxmlconftest.c
index 757f0a9fc0..0c146601ed 100644
--- a/tests/qemuxmlconftest.c
+++ b/tests/qemuxmlconftest.c
@@ -378,6 +378,48 @@ testSetupHostdevPrivateData(virDomainDef *def)
}
+static void
+testQemuPrepareHostdevUSB(virDomainHostdevDef *hostdev)
+{
+ virDomainHostdevSubsysUSB *usb = &hostdev->source.subsys.u.usb;
+
+ if (!usb->device && !usb->bus) {
+ if (usb->vendor == 0x1234 && usb->product == 0x4321) {
+ usb->bus = 42;
+ usb->device = 0x1234;
+ } else {
+ g_assert_not_reached();
+ }
+ }
+}
+
+
+static void
+testQemuPrepareHostdev(virDomainObj *vm)
+{
+ size_t i;
+
+ for (i = 0; i < vm->def->nhostdevs; i++) {
+ virDomainHostdevDef *hostdev = vm->def->hostdevs[i];
+
+ if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
+ continue;
+
+ switch (hostdev->source.subsys.type) {
+ case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB:
+ testQemuPrepareHostdevUSB(hostdev);
+ break;
+ case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI:
+ case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI:
+ case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST:
+ case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_MDEV:
+ case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST:
+ break;
+ }
+ }
+}
+
+
static virNetworkDriver fakeNetworkDriver = {
.networkLookupByName = fakeNetworkLookupByName,
.networkGetXMLDesc = fakeNetworkGetXMLDesc,
@@ -524,22 +566,7 @@ testCompareXMLToArgvCreateArgs(virQEMUDriver *drv,
}
}
- 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_USB) {
- virDomainHostdevSubsysUSB *usb = &hostdev->source.subsys.u.usb;
- if (!usb->device && !usb->bus) {
- if (usb->vendor == 0x1234 && usb->product == 0x4321) {
- usb->bus = 42;
- usb->device = 0x1234;
- } else {
- g_assert_not_reached();
- }
- }
- }
- }
+ testQemuPrepareHostdev(vm);
if (flags & FLAG_SLIRP_HELPER) {
for (i = 0; i < vm->def->nnets; i++) {
--
2.53.0

View File

@ -0,0 +1,78 @@
From ef36f155015cd42f1f631d4955b76173ca16b9f3 Mon Sep 17 00:00:00 2001
Message-ID: <ef36f155015cd42f1f631d4955b76173ca16b9f3.1771423659.git.jdenemar@redhat.com>
From: Pavel Hrdina <phrdina@redhat.com>
Date: Sat, 14 Feb 2026 11:48:53 +0100
Subject: [PATCH] qemuxmlconftest: Rename and refactor
testSetupHostdevPrivateData
There is no need to call qemuDomainHostdevPrivateNew() because
privateData is allocated on creation by virDomainHostdevDefNew().
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit 15ad45758bcb674924ddb2ebb86a767cf40b990d)
Resolves: https://issues.redhat.com/browse/RHEL-150351
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
---
tests/qemuxmlconftest.c | 29 +++++++----------------------
1 file changed, 7 insertions(+), 22 deletions(-)
diff --git a/tests/qemuxmlconftest.c b/tests/qemuxmlconftest.c
index 0c146601ed..f7e50dc655 100644
--- a/tests/qemuxmlconftest.c
+++ b/tests/qemuxmlconftest.c
@@ -352,28 +352,13 @@ fakeNetworkPortGetXMLDesc(virNetworkPortPtr port,
static void
-testSetupHostdevPrivateData(virDomainDef *def)
+testQemuPrepareHostdevPCI(virDomainHostdevDef *hostdev)
{
- size_t i;
+ qemuDomainHostdevPrivate *hostdevPriv = QEMU_DOMAIN_HOSTDEV_PRIVATE(hostdev);
- for (i = 0; i < def->nhostdevs; i++) {
- virDomainHostdevDef *hostdev = 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) {
-
- qemuDomainHostdevPrivate *priv;
-
- if (!hostdev->privateData) {
- hostdev->privateData = qemuDomainHostdevPrivateNew();
- }
-
- priv = QEMU_DOMAIN_HOSTDEV_PRIVATE(hostdev);
- /* Use a placeholder FD value for tests */
- priv->vfioDeviceFd = 0;
- }
+ if (virHostdevIsPCIDeviceWithIOMMUFD(hostdev)) {
+ /* Use a placeholder FD value for tests */
+ hostdevPriv->vfioDeviceFd = 0;
}
}
@@ -410,6 +395,8 @@ testQemuPrepareHostdev(virDomainObj *vm)
testQemuPrepareHostdevUSB(hostdev);
break;
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI:
+ testQemuPrepareHostdevPCI(hostdev);
+ break;
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI:
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST:
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_MDEV:
@@ -473,8 +460,6 @@ testCompareXMLToArgvCreateArgs(virQEMUDriver *drv,
if (testQemuPrepareHostBackendChardevOne(NULL, priv->monConfig, vm) < 0)
return NULL;
- testSetupHostdevPrivateData(vm->def);
-
for (i = 0; i < vm->def->ndisks; i++) {
virDomainDiskDef *disk = vm->def->disks[i];
virStorageSource *src;
--
2.53.0

View File

@ -0,0 +1,98 @@
From fc19eece815873aa653d733494294f4b83a9416e Mon Sep 17 00:00:00 2001
Message-ID: <fc19eece815873aa653d733494294f4b83a9416e.1771423659.git.jdenemar@redhat.com>
From: Pavel Hrdina <phrdina@redhat.com>
Date: Sat, 14 Feb 2026 17:11:44 +0100
Subject: [PATCH] qemuxmlconftest: Set fake FD for IOMMUFD
Same as for VFIO FD for host device.
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit 4a80a0468e21866d11f08bd64888f399cff98d94)
Resolves: https://issues.redhat.com/browse/RHEL-150351
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
---
tests/qemuxmlconfdata/iommufd-q35.x86_64-latest.args | 2 +-
.../iommufd-virt-pci-bus-single.aarch64-latest.args | 2 +-
tests/qemuxmlconfdata/iommufd-virt.aarch64-latest.args | 2 +-
tests/qemuxmlconfdata/iommufd.x86_64-latest.args | 2 +-
tests/qemuxmlconftest.c | 4 ++++
5 files changed, 8 insertions(+), 4 deletions(-)
diff --git a/tests/qemuxmlconfdata/iommufd-q35.x86_64-latest.args b/tests/qemuxmlconfdata/iommufd-q35.x86_64-latest.args
index 7d819e141b..d5fe704021 100644
--- a/tests/qemuxmlconfdata/iommufd-q35.x86_64-latest.args
+++ b/tests/qemuxmlconfdata/iommufd-q35.x86_64-latest.args
@@ -35,7 +35,7 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-q35-test/.config \
-device '{"driver":"qxl-vga","id":"video0","max_outputs":1,"ram_size":67108864,"vram_size":33554432,"vram64_size_mb":0,"vgamem_mb":8,"bus":"pcie.0","addr":"0x1"}' \
-global ICH9-LPC.noreboot=off \
-watchdog-action reset \
--object '{"qom-type":"iommufd","id":"iommufd0","fd":"-1"}' \
+-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"}' \
-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 dbfd395168..99886468fb 100644
--- a/tests/qemuxmlconfdata/iommufd-virt-pci-bus-single.aarch64-latest.args
+++ b/tests/qemuxmlconfdata/iommufd-virt-pci-bus-single.aarch64-latest.args
@@ -27,7 +27,7 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-foo/.config \
-no-shutdown \
-boot strict=on \
-audiodev '{"id":"audio1","driver":"none"}' \
--object '{"qom-type":"iommufd","id":"iommufd0","fd":"-1"}' \
+-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"}' \
-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 d5713ff826..e3695c6982 100644
--- a/tests/qemuxmlconfdata/iommufd-virt.aarch64-latest.args
+++ b/tests/qemuxmlconfdata/iommufd-virt.aarch64-latest.args
@@ -30,7 +30,7 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-foo/.config \
-device '{"driver":"pcie-root-port","port":9,"chassis":2,"id":"pci.2","bus":"pcie.0","addr":"0x1.0x1"}' \
-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":"-1"}' \
+-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"}' \
-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \
diff --git a/tests/qemuxmlconfdata/iommufd.x86_64-latest.args b/tests/qemuxmlconfdata/iommufd.x86_64-latest.args
index 3130ba2e3a..15dabe197c 100644
--- a/tests/qemuxmlconfdata/iommufd.x86_64-latest.args
+++ b/tests/qemuxmlconfdata/iommufd.x86_64-latest.args
@@ -28,7 +28,7 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-foo/.config \
-boot strict=on \
-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":"-1"}' \
+-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":"virtio-balloon-pci","id":"balloon0","bus":"pci.0","addr":"0x2"}' \
-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \
diff --git a/tests/qemuxmlconftest.c b/tests/qemuxmlconftest.c
index f7e50dc655..6f16b6cee8 100644
--- a/tests/qemuxmlconftest.c
+++ b/tests/qemuxmlconftest.c
@@ -382,6 +382,7 @@ testQemuPrepareHostdevUSB(virDomainHostdevDef *hostdev)
static void
testQemuPrepareHostdev(virDomainObj *vm)
{
+ qemuDomainObjPrivate *priv = QEMU_DOMAIN_PRIVATE(vm);
size_t i;
for (i = 0; i < vm->def->nhostdevs; i++) {
@@ -404,6 +405,9 @@ testQemuPrepareHostdev(virDomainObj *vm)
break;
}
}
+
+ if (virDomainDefHasPCIHostdevWithIOMMUFD(vm->def))
+ priv->iommufd = 0;
}
--
2.53.0

View File

@ -0,0 +1,113 @@
From 89d43d156f8a5c2fbb48947885e98c27b0617f0f Mon Sep 17 00:00:00 2001
Message-ID: <89d43d156f8a5c2fbb48947885e98c27b0617f0f.1771423659.git.jdenemar@redhat.com>
From: Pavel Hrdina <phrdina@redhat.com>
Date: Mon, 16 Feb 2026 16:53:57 +0100
Subject: [PATCH] tests: properly mock VFIO and IOMMU checks
Fixes: 63434db800b921e96fec424a667b7161af1f02de
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
(cherry picked from commit 75db232f90af2b2acd95266dd21290c967e3c625)
Resolves: https://issues.redhat.com/browse/RHEL-148135
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
---
src/util/virutil.h | 2 +-
tests/domaincapsdata/qemu_9.0.0.sparc.xml | 5 +----
tests/domaincapsdata/qemu_9.2.0-hvf.aarch64+hvf.xml | 5 +----
tests/domaincapsmock.c | 10 ++++++++++
tests/domaincapstest.c | 8 --------
5 files changed, 13 insertions(+), 17 deletions(-)
diff --git a/src/util/virutil.h b/src/util/virutil.h
index ca6fd95363..7e1705e7ce 100644
--- a/src/util/virutil.h
+++ b/src/util/virutil.h
@@ -141,7 +141,7 @@ unsigned long long virMemoryLimitTruncate(unsigned long long value);
bool virMemoryLimitIsSet(unsigned long long value);
unsigned long long virMemoryMaxValue(bool ulong) ATTRIBUTE_MOCKABLE;
-bool virHostHasIOMMU(void);
+bool virHostHasIOMMU(void) ATTRIBUTE_MOCKABLE;
char *virHostGetDRMRenderNode(void) ATTRIBUTE_MOCKABLE;
diff --git a/tests/domaincapsdata/qemu_9.0.0.sparc.xml b/tests/domaincapsdata/qemu_9.0.0.sparc.xml
index 062e55718b..93d8d40c2c 100644
--- a/tests/domaincapsdata/qemu_9.0.0.sparc.xml
+++ b/tests/domaincapsdata/qemu_9.0.0.sparc.xml
@@ -86,10 +86,7 @@
<value>scsi</value>
</enum>
<enum name='capsType'/>
- <enum name='pciBackend'>
- <value>default</value>
- <value>vfio</value>
- </enum>
+ <enum name='pciBackend'/>
<enum name='iommufd'>
<value>no</value>
</enum>
diff --git a/tests/domaincapsdata/qemu_9.2.0-hvf.aarch64+hvf.xml b/tests/domaincapsdata/qemu_9.2.0-hvf.aarch64+hvf.xml
index db51e7b120..a65d9d36fd 100644
--- a/tests/domaincapsdata/qemu_9.2.0-hvf.aarch64+hvf.xml
+++ b/tests/domaincapsdata/qemu_9.2.0-hvf.aarch64+hvf.xml
@@ -147,10 +147,7 @@
<value>scsi</value>
</enum>
<enum name='capsType'/>
- <enum name='pciBackend'>
- <value>default</value>
- <value>vfio</value>
- </enum>
+ <enum name='pciBackend'/>
<enum name='iommufd'>
<value>no</value>
</enum>
diff --git a/tests/domaincapsmock.c b/tests/domaincapsmock.c
index 370ce35709..aa13deb324 100644
--- a/tests/domaincapsmock.c
+++ b/tests/domaincapsmock.c
@@ -21,6 +21,7 @@
#include "virhostmem.h"
#include "viriommufd.h"
#include "virmock.h"
+#include "virutil.h"
#if WITH_QEMU
# include "qemu/qemu_capabilities.h"
@@ -91,5 +92,14 @@ virFileExists(const char *path)
if (STREQ(path, VIR_IOMMU_DEV_PATH))
return true;
+ if (STREQ(path, "/dev/vfio/vfio"))
+ return true;
+
return real_virFileExists(path);
}
+
+bool
+virHostHasIOMMU(void)
+{
+ return true;
+}
diff --git a/tests/domaincapstest.c b/tests/domaincapstest.c
index 71e181d179..5b2fc80f0a 100644
--- a/tests/domaincapstest.c
+++ b/tests/domaincapstest.c
@@ -104,14 +104,6 @@ fillQemuCaps(virDomainCaps *domCaps,
false) < 0)
return -1;
- /* The function above tries to query host's VFIO capabilities by calling
- * virHostdevHostSupportsPassthroughVFIO() which, however, can't be
- * successfully mocked as they are not exposed as internal APIs. Therefore,
- * instead of mocking set the expected values here by hand. */
- VIR_DOMAIN_CAPS_ENUM_SET(domCaps->hostdev.pciBackend,
- VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_DEFAULT,
- VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_VFIO);
-
/* As of f05b6a918e28 we are expecting to see OVMF_CODE.fd file which
* may not exists everywhere. */
while (loader->values.nvalues)
--
2.53.0

View File

@ -0,0 +1,115 @@
From e0e49da1ab66c90b0379ca246b8bdfeadb9ebdbe Mon Sep 17 00:00:00 2001
Message-ID: <e0e49da1ab66c90b0379ca246b8bdfeadb9ebdbe.1771423658.git.jdenemar@redhat.com>
From: Pavel Hrdina <phrdina@redhat.com>
Date: Sun, 15 Feb 2026 15:32:24 +0100
Subject: [PATCH] util: Move openning IOMMU device to viriommufd
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit c684b83a68158cd15e262523db11259c9edabe4a)
Resolves: https://issues.redhat.com/browse/RHEL-150351
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
---
src/libvirt_private.syms | 2 +-
src/qemu/qemu_process.c | 9 +--------
src/util/viriommufd.c | 22 +++++++++++++++++++---
src/util/viriommufd.h | 2 +-
4 files changed, 22 insertions(+), 13 deletions(-)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 0904265459..6c4918da9e 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -2653,7 +2653,7 @@ virInitctlFifos;
virInitctlSetRunLevel;
# util/viriommufd.h
-virIOMMUFDSetRLimitMode;
+virIOMMUFDOpenDevice;
virIOMMUFDSupported;
# util/viriscsi.h
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 479437fb34..dd165512f3 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -7689,15 +7689,8 @@ 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) {
- virReportSystemError(errno, "%s", _("cannot open /dev/iommu"));
+ if ((fd = virIOMMUFDOpenDevice()) < 0)
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;
diff --git a/src/util/viriommufd.c b/src/util/viriommufd.c
index 44b30029a5..1f3353eab4 100644
--- a/src/util/viriommufd.c
+++ b/src/util/viriommufd.c
@@ -1,5 +1,7 @@
#include <config.h>
+#include <fcntl.h>
+
#include "viriommufd.h"
#include "virlog.h"
#include "virerror.h"
@@ -54,7 +56,7 @@ struct iommu_option {
*
* Returns: 0 on success, -1 on error
*/
-int
+static int
virIOMMUFDSetRLimitMode(int fd, bool processAccounting)
{
struct iommu_option option = {
@@ -77,10 +79,24 @@ virIOMMUFDSetRLimitMode(int fd, bool processAccounting)
return 0;
}
+int
+virIOMMUFDOpenDevice(void)
+{
+ int fd = -1;
+
+ if ((fd = open(VIR_IOMMU_DEV_PATH, O_RDWR | O_CLOEXEC)) < 0)
+ virReportSystemError(errno, "%s", _("cannot open IOMMUFD device"));
+
+ if (virIOMMUFDSetRLimitMode(fd, true) < 0)
+ return -1;
+
+ return fd;
+}
+
#else
-int virIOMMUFDSetRLimitMode(int fd G_GNUC_UNUSED,
- bool processAccounting G_GNUC_UNUSED)
+int
+virIOMMUFDOpenDevice(void)
{
virReportError(VIR_ERR_NO_SUPPORT, "%s",
_("IOMMUFD is not supported on this platform"));
diff --git a/src/util/viriommufd.h b/src/util/viriommufd.h
index ec6be9fa66..223f44eb5c 100644
--- a/src/util/viriommufd.h
+++ b/src/util/viriommufd.h
@@ -22,6 +22,6 @@
#define VIR_IOMMU_DEV_PATH "/dev/iommu"
-int virIOMMUFDSetRLimitMode(int fd, bool processAccounting);
+int virIOMMUFDOpenDevice(void);
bool virIOMMUFDSupported(void);
--
2.53.0

View File

@ -0,0 +1,123 @@
From d116851dc65d69b95d9de2f0f209ba5d69987cb8 Mon Sep 17 00:00:00 2001
Message-ID: <d116851dc65d69b95d9de2f0f209ba5d69987cb8.1771423658.git.jdenemar@redhat.com>
From: Pavel Hrdina <phrdina@redhat.com>
Date: Sun, 15 Feb 2026 17:39:05 +0100
Subject: [PATCH] util: Move openning VFIO device to virpci
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit 22c666097cc56919355e653010bff8ade5d5f12c)
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 | 23 +----------------------
src/util/virpci.c | 28 ++++++++++++++++++++++++++++
src/util/virpci.h | 2 ++
4 files changed, 32 insertions(+), 22 deletions(-)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 6c4918da9e..9ae44e31b8 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -3180,6 +3180,7 @@ virPCIDeviceListNew;
virPCIDeviceListSteal;
virPCIDeviceListStealIndex;
virPCIDeviceNew;
+virPCIDeviceOpenVfioFd;
virPCIDeviceReattach;
virPCIDeviceRebind;
virPCIDeviceReset;
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 71770d2099..55cd930df8 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -7707,9 +7707,6 @@ qemuProcessOpenIommuFd(virDomainObj *vm)
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",
@@ -7717,25 +7714,7 @@ qemuProcessOpenVfioDeviceFd(virDomainHostdevDef *hostdev)
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;
+ return virPCIDeviceOpenVfioFd(&hostdev->source.subsys.u.pci.addr);
}
/**
diff --git a/src/util/virpci.c b/src/util/virpci.c
index 2348a98003..30feec6dae 100644
--- a/src/util/virpci.c
+++ b/src/util/virpci.c
@@ -3359,3 +3359,31 @@ virPCIDeviceGetVfioPath(virPCIDeviceAddress *addr,
addrStr);
return -1;
}
+
+/**
+ * virPCIDeviceOpenVfioFd:
+ * @addr:
+ *
+ * Opens VFIO device and returns its FD.
+ *
+ * Returns: FD on success, -1 on failure
+ */
+int
+virPCIDeviceOpenVfioFd(virPCIDeviceAddress *addr)
+{
+ g_autofree char *vfioPath = NULL;
+ int fd = -1;
+
+ if (virPCIDeviceGetVfioPath(addr, &vfioPath) < 0)
+ return -1;
+
+ VIR_DEBUG("Opening VFIO device %s", vfioPath);
+
+ if ((fd = open(vfioPath, O_RDWR | O_CLOEXEC)) < 0) {
+ virReportSystemError(errno, _("cannot open VFIO device %1$s"), vfioPath);
+ return -1;
+ }
+
+ VIR_DEBUG("Opened VFIO device FD %d for %s", fd, vfioPath);
+ return fd;
+}
diff --git a/src/util/virpci.h b/src/util/virpci.h
index 24ede10755..7848567285 100644
--- a/src/util/virpci.h
+++ b/src/util/virpci.h
@@ -298,6 +298,8 @@ void virPCIDeviceAddressFree(virPCIDeviceAddress *address);
int virPCIDeviceGetVfioPath(virPCIDeviceAddress *addr, char **vfioPath);
+int virPCIDeviceOpenVfioFd(virPCIDeviceAddress *addr);
+
G_DEFINE_AUTOPTR_CLEANUP_FUNC(virPCIDevice, virPCIDeviceFree);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(virPCIDeviceAddress, virPCIDeviceAddressFree);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(virPCIEDeviceInfo, virPCIEDeviceInfoFree);
--
2.53.0

View File

@ -0,0 +1,143 @@
From 25fa4eb529f1d54995b66ebe3b38bafb3ab755c6 Mon Sep 17 00:00:00 2001
Message-ID: <25fa4eb529f1d54995b66ebe3b38bafb3ab755c6.1771423658.git.jdenemar@redhat.com>
From: Pavel Hrdina <phrdina@redhat.com>
Date: Sun, 15 Feb 2026 17:51:46 +0100
Subject: [PATCH] util: Use virPCIDevice as argument in virPCIDeviceGetVfioPath
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit 3365bff598a0d0a5b21afc7060e10a0a2f7d21a7)
Resolves: https://issues.redhat.com/browse/RHEL-150351
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
---
src/security/security_apparmor.c | 2 +-
src/security/security_dac.c | 4 ++--
src/security/security_selinux.c | 4 ++--
src/util/virpci.c | 14 ++++++++------
src/util/virpci.h | 2 +-
5 files changed, 14 insertions(+), 12 deletions(-)
diff --git a/src/security/security_apparmor.c b/src/security/security_apparmor.c
index 934acfb461..6c5da2a650 100644
--- a/src/security/security_apparmor.c
+++ b/src/security/security_apparmor.c
@@ -860,7 +860,7 @@ AppArmorSetSecurityHostdevLabel(virSecurityManager *mgr,
} else {
g_autofree char *vfiofdDev = NULL;
- if (virPCIDeviceGetVfioPath(&dev->source.subsys.u.pci.addr, &vfiofdDev) < 0)
+ if (virPCIDeviceGetVfioPath(pci, &vfiofdDev) < 0)
goto done;
ret = AppArmorSetSecurityPCILabel(pci, vfiofdDev, ptr);
diff --git a/src/security/security_dac.c b/src/security/security_dac.c
index d0ed22db2d..704c8dbfec 100644
--- a/src/security/security_dac.c
+++ b/src/security/security_dac.c
@@ -1295,7 +1295,7 @@ virSecurityDACSetHostdevLabel(virSecurityManager *mgr,
} else {
g_autofree char *vfiofdDev = NULL;
- if (virPCIDeviceGetVfioPath(&dev->source.subsys.u.pci.addr, &vfiofdDev) < 0)
+ if (virPCIDeviceGetVfioPath(pci, &vfiofdDev) < 0)
return -1;
ret = virSecurityDACSetHostdevLabelHelper(vfiofdDev, false, &cbdata);
@@ -1468,7 +1468,7 @@ virSecurityDACRestoreHostdevLabel(virSecurityManager *mgr,
} else {
g_autofree char *vfiofdDev = NULL;
- if (virPCIDeviceGetVfioPath(&dev->source.subsys.u.pci.addr, &vfiofdDev) < 0)
+ if (virPCIDeviceGetVfioPath(pci, &vfiofdDev) < 0)
return -1;
ret = virSecurityDACRestoreFileLabelInternal(mgr, NULL,
diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c
index 834383a7de..4a5f61d16b 100644
--- a/src/security/security_selinux.c
+++ b/src/security/security_selinux.c
@@ -2269,7 +2269,7 @@ virSecuritySELinuxSetHostdevSubsysLabel(virSecurityManager *mgr,
} else {
g_autofree char *vfiofdDev = NULL;
- if (virPCIDeviceGetVfioPath(&dev->source.subsys.u.pci.addr, &vfiofdDev) < 0)
+ if (virPCIDeviceGetVfioPath(pci, &vfiofdDev) < 0)
return -1;
ret = virSecuritySELinuxSetHostdevLabelHelper(vfiofdDev, false, &data);
@@ -2515,7 +2515,7 @@ virSecuritySELinuxRestoreHostdevSubsysLabel(virSecurityManager *mgr,
} else {
g_autofree char *vfiofdDev = NULL;
- if (virPCIDeviceGetVfioPath(&dev->source.subsys.u.pci.addr, &vfiofdDev) < 0)
+ if (virPCIDeviceGetVfioPath(pci, &vfiofdDev) < 0)
return -1;
ret = virSecuritySELinuxRestoreFileLabel(mgr, vfiofdDev, false, false);
diff --git a/src/util/virpci.c b/src/util/virpci.c
index 30feec6dae..78c47869ef 100644
--- a/src/util/virpci.c
+++ b/src/util/virpci.c
@@ -3331,19 +3331,17 @@ virPCIDeviceAddressFree(virPCIDeviceAddress *address)
* Returns: 0 on success, -1 on failure
*/
int
-virPCIDeviceGetVfioPath(virPCIDeviceAddress *addr,
+virPCIDeviceGetVfioPath(virPCIDevice *pci,
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);
+ sysfsPath = virPCIFile(pci->name, "vfio-dev");
if (virDirOpen(&dir, sysfsPath) == 1) {
while (virDirRead(dir, &entry, sysfsPath) > 0) {
@@ -3356,7 +3354,7 @@ virPCIDeviceGetVfioPath(virPCIDeviceAddress *addr,
virReportError(VIR_ERR_INTERNAL_ERROR,
_("cannot find VFIO device for PCI device %1$s"),
- addrStr);
+ pci->name);
return -1;
}
@@ -3371,10 +3369,14 @@ virPCIDeviceGetVfioPath(virPCIDeviceAddress *addr,
int
virPCIDeviceOpenVfioFd(virPCIDeviceAddress *addr)
{
+ g_autoptr(virPCIDevice) pci = NULL;
g_autofree char *vfioPath = NULL;
int fd = -1;
- if (virPCIDeviceGetVfioPath(addr, &vfioPath) < 0)
+ if (!(pci = virPCIDeviceNew(addr)))
+ return -1;
+
+ if (virPCIDeviceGetVfioPath(pci, &vfioPath) < 0)
return -1;
VIR_DEBUG("Opening VFIO device %s", vfioPath);
diff --git a/src/util/virpci.h b/src/util/virpci.h
index 7848567285..933099da6c 100644
--- a/src/util/virpci.h
+++ b/src/util/virpci.h
@@ -296,7 +296,7 @@ void virPCIEDeviceInfoFree(virPCIEDeviceInfo *dev);
void virPCIDeviceAddressFree(virPCIDeviceAddress *address);
-int virPCIDeviceGetVfioPath(virPCIDeviceAddress *addr, char **vfioPath);
+int virPCIDeviceGetVfioPath(virPCIDevice *pci, char **vfioPath);
int virPCIDeviceOpenVfioFd(virPCIDeviceAddress *addr);
--
2.53.0

View File

@ -294,7 +294,7 @@
Summary: Library providing a simple virtualization API
Name: libvirt
Version: 11.10.0
Release: 9%{?dist}%{?extra_release}
Release: 10%{?dist}%{?extra_release}
License: GPL-2.0-or-later AND LGPL-2.1-only AND LGPL-2.1-or-later AND OFL-1.1
URL: https://libvirt.org/
@ -355,6 +355,32 @@ Patch50: libvirt-docs-formatdomain-Fix-indentation-of-docs-for-disk-driver-stati
Patch51: libvirt-docs-formatdomain-Reword-section-about-the-statistics-element-under-disk-driver.patch
Patch52: libvirt-Introduce-support-for-disk-operation-latency-histogram-collection.patch
Patch53: libvirt-qemu-Setup-disk-latency-histograms-on-startup-hotplug-update.patch
Patch54: libvirt-qemu-Introduce-QEMU_CAPS_OBJECT_IOMMUFD.patch
Patch55: libvirt-qemu-Move-IOMMUFD-validation-to-qemu_validate.patch
Patch56: libvirt-util-Move-openning-IOMMU-device-to-viriommufd.patch
Patch57: libvirt-qemu_process-Refactor-qemuProcessOpenIommuFd.patch
Patch58: libvirt-util-Move-openning-VFIO-device-to-virpci.patch
Patch59: libvirt-qemu_process-Refactor-qemuProcessOpenVfioDeviceFd.patch
Patch60: libvirt-util-Use-virPCIDevice-as-argument-in-virPCIDeviceGetVfioPath.patch
Patch61: libvirt-conf-Introduce-virHostdevIsPCIDeviceWithIOMMUFD.patch
Patch62: libvirt-conf-Introduce-virDomainDefHasPCIHostdevWithIOMMUFD.patch
Patch63: libvirt-qemu_domain-Add-missing-IOMMUFD-cleanup.patch
Patch64: libvirt-qemu_process-Fix-FD-leak-with-multiple-host-devices-using-IOMMUFD.patch
Patch65: libvirt-qemu_process-Refactor-qemuProcessOpenVfioFds.patch
Patch66: libvirt-qemuxmlconftest-Refactor-host-device-preparation.patch
Patch67: libvirt-qemuxmlconftest-Rename-and-refactor-testSetupHostdevPrivateData.patch
Patch68: libvirt-qemuxmlconftest-Set-fake-FD-for-IOMMUFD.patch
Patch69: libvirt-qemu-Convert-IOMMUFD-to-qemuFDPassDirect.patch
Patch70: libvirt-qemu-Convert-vfioDeviceFd-to-qemuFDPassDirect.patch
Patch71: libvirt-qemu_command-Don-t-use-host-property-if-IOMMUFD-is-used.patch
Patch72: libvirt-qemu-Save-IOMMUFD-state-into-status-XML.patch
Patch73: libvirt-qemu_hotplug-Remove-iommufd-object-if-no-longer-needed.patch
Patch74: libvirt-qemu_command-Extract-building-IOMMUFD-props-to-function.patch
Patch75: libvirt-qemu_hotplug-Add-support-to-hotplug-host-device-with-IOMMUFD.patch
Patch76: libvirt-conf-Introduce-iommufd-enum-for-domaincaps.patch
Patch77: libvirt-qemu-Fill-iommufd-domain-capability.patch
Patch78: libvirt-tests-properly-mock-VFIO-and-IOMMU-checks.patch
Patch79: libvirt-iommufd-fix-FD-leak-in-case-of-error.patch
Requires: libvirt-daemon = %{version}-%{release}
@ -2746,6 +2772,34 @@ exit 0
%endif
%changelog
* Wed Feb 18 2026 Jiri Denemark <jdenemar@redhat.com> - 11.10.0-10
- qemu: Introduce QEMU_CAPS_OBJECT_IOMMUFD (RHEL-150351)
- qemu: Move IOMMUFD validation to qemu_validate (RHEL-150351)
- util: Move openning IOMMU device to viriommufd (RHEL-150351)
- qemu_process: Refactor qemuProcessOpenIommuFd (RHEL-150351)
- util: Move openning VFIO device to virpci (RHEL-150351)
- qemu_process: Refactor qemuProcessOpenVfioDeviceFd (RHEL-150351)
- util: Use virPCIDevice as argument in virPCIDeviceGetVfioPath (RHEL-150351)
- conf: Introduce virHostdevIsPCIDeviceWithIOMMUFD (RHEL-150351)
- conf: Introduce virDomainDefHasPCIHostdevWithIOMMUFD (RHEL-150351)
- qemu_domain: Add missing IOMMUFD cleanup (RHEL-150351)
- qemu_process: Fix FD leak with multiple host devices using IOMMUFD (RHEL-150351)
- qemu_process: Refactor qemuProcessOpenVfioFds (RHEL-150351)
- qemuxmlconftest: Refactor host device preparation (RHEL-150351)
- qemuxmlconftest: Rename and refactor testSetupHostdevPrivateData (RHEL-150351)
- qemuxmlconftest: Set fake FD for IOMMUFD (RHEL-150351)
- qemu: Convert IOMMUFD to qemuFDPassDirect (RHEL-150351)
- qemu: Convert vfioDeviceFd to qemuFDPassDirect (RHEL-150351)
- qemu_command: Don't use host property if IOMMUFD is used (RHEL-150351)
- qemu: Save IOMMUFD state into status XML (RHEL-150351)
- qemu_hotplug: Remove iommufd object if no longer needed (RHEL-150351)
- qemu_command: Extract building IOMMUFD props to function (RHEL-150351)
- qemu_hotplug: Add support to hotplug host device with IOMMUFD (RHEL-150351)
- conf: Introduce iommufd enum for domaincaps (RHEL-148135)
- qemu: Fill iommufd domain capability (RHEL-148135)
- tests: properly mock VFIO and IOMMU checks (RHEL-148135)
- iommufd: fix FD leak in case of error (RHEL-150351)
* Tue Feb 17 2026 Jiri Denemark <jdenemar@redhat.com> - 11.10.0-9
- qemu: capabilities: Probe properties of 'scsi-block' and 'scsi-generic' devices (RHEL-135115)
- qemu: capabilities: Introduce QEMU_CAPS_DEVICE_SCSI_BLOCK_MIGRATE_PR (RHEL-135115)