libvirt-11.10.0-10.el9

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

Resolves: RHEL-138544, RHEL-150353
This commit is contained in:
Jiri Denemark 2026-02-18 15:10:32 +01:00
parent 529ceed52e
commit 420786d401
27 changed files with 3807 additions and 1 deletions

View File

@ -0,0 +1,69 @@
From 18aa061f3b4f2b2c2ed6f07120a990935f56d93e Mon Sep 17 00:00:00 2001
Message-ID: <18aa061f3b4f2b2c2ed6f07120a990935f56d93e.1771423832.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-138544
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 748c9648eb88b69e3ed0847126d59d6c7a11eda8 Mon Sep 17 00:00:00 2001
Message-ID: <748c9648eb88b69e3ed0847126d59d6c7a11eda8.1771423832.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-150353
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 1718097b63..482f8d8ca2 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 3864161a4d28f0ef71d435f2ae1e52e92afaac15 Mon Sep 17 00:00:00 2001
Message-ID: <3864161a4d28f0ef71d435f2ae1e52e92afaac15.1771423832.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-150353
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 05df8c7309ca3c7db2f5a3c4eb1d07a48aaab486 Mon Sep 17 00:00:00 2001
Message-ID: <05df8c7309ca3c7db2f5a3c4eb1d07a48aaab486.1771423832.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-150353
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 ca83d49a04eb50ecb5bff8dde9928a9c15764fee Mon Sep 17 00:00:00 2001
Message-ID: <ca83d49a04eb50ecb5bff8dde9928a9c15764fee.1771423832.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-150353
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 482f8d8ca2..0057934cc6 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 885512a38c..eeb9298b2e 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 24b8d8f936dcff1a78dda3253876f9242b3ec98b Mon Sep 17 00:00:00 2001
Message-ID: <24b8d8f936dcff1a78dda3253876f9242b3ec98b.1771423832.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-150353
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 0057934cc6..8038aa3115 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 eeb9298b2e..aa877bf16a 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 634e8902ffca6246e5066816d52063f3c82dddb7 Mon Sep 17 00:00:00 2001
Message-ID: <634e8902ffca6246e5066816d52063f3c82dddb7.1771423832.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-150353
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 9ab285f768..9886ddaf1d 100644
--- a/src/qemu/qemu_validate.c
+++ b/src/qemu/qemu_validate.c
@@ -2720,6 +2720,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 38c43950b3f6327e5d51e6751415208e5a467bed Mon Sep 17 00:00:00 2001
Message-ID: <38c43950b3f6327e5d51e6751415208e5a467bed.1771423832.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-150353
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 9886ddaf1d..5c8c21335d 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"
@@ -2727,6 +2728,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 c061be3f01ee2e1b6138a440bbd137bdb71e785f Mon Sep 17 00:00:00 2001
Message-ID: <c061be3f01ee2e1b6138a440bbd137bdb71e785f.1771423832.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-150353
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 445d328358..b866c690ae 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 286c9b1d27777ce5794583d94f0dfe2aed5d46c3 Mon Sep 17 00:00:00 2001
Message-ID: <286c9b1d27777ce5794583d94f0dfe2aed5d46c3.1771423832.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-150353
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 8038aa3115..445d328358 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 a4c573319fc93a7279119df6fa3b2ff3e34bb404 Mon Sep 17 00:00:00 2001
Message-ID: <a4c573319fc93a7279119df6fa3b2ff3e34bb404.1771423832.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-150353
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 b866c690ae..db512f6757 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 71ada452d793af287917d562e6b4326201fa48d2 Mon Sep 17 00:00:00 2001
Message-ID: <71ada452d793af287917d562e6b4326201fa48d2.1771423832.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-150353
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 85d04af274dbda131798bbce63773f8b71639723 Mon Sep 17 00:00:00 2001
Message-ID: <85d04af274dbda131798bbce63773f8b71639723.1771423832.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-150353
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 28d5107c5ce7488664cedd82565167e6df7b61de Mon Sep 17 00:00:00 2001
Message-ID: <28d5107c5ce7488664cedd82565167e6df7b61de.1771423832.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-150353
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 84ff22de6dd06a6e63cb989cf58ec0e8eb44fb06 Mon Sep 17 00:00:00 2001
Message-ID: <84ff22de6dd06a6e63cb989cf58ec0e8eb44fb06.1771423832.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-150353
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 cad077e78e649f2d076170228476bff939d2af67 Mon Sep 17 00:00:00 2001
Message-ID: <cad077e78e649f2d076170228476bff939d2af67.1771423832.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-150353
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 65e187a6570ba7d7fa4eeff42353d6aa3f6f802d Mon Sep 17 00:00:00 2001
Message-ID: <65e187a6570ba7d7fa4eeff42353d6aa3f6f802d.1771423832.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-150353
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 eb555cecb3894ddc890c9f0fc099d2210b2bfb62 Mon Sep 17 00:00:00 2001
Message-ID: <eb555cecb3894ddc890c9f0fc099d2210b2bfb62.1771423832.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-150353
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 276b0655a20762b1267a9e4212d266d632633103 Mon Sep 17 00:00:00 2001
Message-ID: <276b0655a20762b1267a9e4212d266d632633103.1771423832.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-150353
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 27e63cff24..7c2dc3697b 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 65c6fc2f31c865cbdd98f9c2edf28727d71486eb Mon Sep 17 00:00:00 2001
Message-ID: <65c6fc2f31c865cbdd98f9c2edf28727d71486eb.1771423832.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-150353
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 7c2dc3697b..8275eacb3e 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 8f562433cdcff89930c3a9ffac26803e733b796e Mon Sep 17 00:00:00 2001
Message-ID: <8f562433cdcff89930c3a9ffac26803e733b796e.1771423832.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-150353
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 8275eacb3e..885512a38c 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 2d5bf873ca8aad6e2e0a151a427bbfdb6d93c766 Mon Sep 17 00:00:00 2001
Message-ID: <2d5bf873ca8aad6e2e0a151a427bbfdb6d93c766.1771423832.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-138544
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 3fab098321e026e0ee33c8ef3c3e45f9976375d9 Mon Sep 17 00:00:00 2001
Message-ID: <3fab098321e026e0ee33c8ef3c3e45f9976375d9.1771423832.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-150353
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 1fd6e9c874704fd5f13d7234424006061f8bbe8a Mon Sep 17 00:00:00 2001
Message-ID: <1fd6e9c874704fd5f13d7234424006061f8bbe8a.1771423832.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-150353
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 065abe6cc4235f285ac2722604c6f4b722f251c3 Mon Sep 17 00:00:00 2001
Message-ID: <065abe6cc4235f285ac2722604c6f4b722f251c3.1771423832.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-150353
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/
@ -350,6 +350,32 @@ Patch45: libvirt-docs-formatdomain-Fix-indentation-of-docs-for-disk-driver-stati
Patch46: libvirt-docs-formatdomain-Reword-section-about-the-statistics-element-under-disk-driver.patch
Patch47: libvirt-Introduce-support-for-disk-operation-latency-histogram-collection.patch
Patch48: libvirt-qemu-Setup-disk-latency-histograms-on-startup-hotplug-update.patch
Patch49: libvirt-qemu-Introduce-QEMU_CAPS_OBJECT_IOMMUFD.patch
Patch50: libvirt-qemu-Move-IOMMUFD-validation-to-qemu_validate.patch
Patch51: libvirt-util-Move-openning-IOMMU-device-to-viriommufd.patch
Patch52: libvirt-qemu_process-Refactor-qemuProcessOpenIommuFd.patch
Patch53: libvirt-util-Move-openning-VFIO-device-to-virpci.patch
Patch54: libvirt-qemu_process-Refactor-qemuProcessOpenVfioDeviceFd.patch
Patch55: libvirt-util-Use-virPCIDevice-as-argument-in-virPCIDeviceGetVfioPath.patch
Patch56: libvirt-conf-Introduce-virHostdevIsPCIDeviceWithIOMMUFD.patch
Patch57: libvirt-conf-Introduce-virDomainDefHasPCIHostdevWithIOMMUFD.patch
Patch58: libvirt-qemu_domain-Add-missing-IOMMUFD-cleanup.patch
Patch59: libvirt-qemu_process-Fix-FD-leak-with-multiple-host-devices-using-IOMMUFD.patch
Patch60: libvirt-qemu_process-Refactor-qemuProcessOpenVfioFds.patch
Patch61: libvirt-qemuxmlconftest-Refactor-host-device-preparation.patch
Patch62: libvirt-qemuxmlconftest-Rename-and-refactor-testSetupHostdevPrivateData.patch
Patch63: libvirt-qemuxmlconftest-Set-fake-FD-for-IOMMUFD.patch
Patch64: libvirt-qemu-Convert-IOMMUFD-to-qemuFDPassDirect.patch
Patch65: libvirt-qemu-Convert-vfioDeviceFd-to-qemuFDPassDirect.patch
Patch66: libvirt-qemu_command-Don-t-use-host-property-if-IOMMUFD-is-used.patch
Patch67: libvirt-qemu-Save-IOMMUFD-state-into-status-XML.patch
Patch68: libvirt-qemu_hotplug-Remove-iommufd-object-if-no-longer-needed.patch
Patch69: libvirt-qemu_command-Extract-building-IOMMUFD-props-to-function.patch
Patch70: libvirt-qemu_hotplug-Add-support-to-hotplug-host-device-with-IOMMUFD.patch
Patch71: libvirt-conf-Introduce-iommufd-enum-for-domaincaps.patch
Patch72: libvirt-qemu-Fill-iommufd-domain-capability.patch
Patch73: libvirt-tests-properly-mock-VFIO-and-IOMMU-checks.patch
Patch74: libvirt-iommufd-fix-FD-leak-in-case-of-error.patch
Requires: libvirt-daemon = %{version}-%{release}
@ -2741,6 +2767,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-150353)
- qemu: Move IOMMUFD validation to qemu_validate (RHEL-150353)
- util: Move openning IOMMU device to viriommufd (RHEL-150353)
- qemu_process: Refactor qemuProcessOpenIommuFd (RHEL-150353)
- util: Move openning VFIO device to virpci (RHEL-150353)
- qemu_process: Refactor qemuProcessOpenVfioDeviceFd (RHEL-150353)
- util: Use virPCIDevice as argument in virPCIDeviceGetVfioPath (RHEL-150353)
- conf: Introduce virHostdevIsPCIDeviceWithIOMMUFD (RHEL-150353)
- conf: Introduce virDomainDefHasPCIHostdevWithIOMMUFD (RHEL-150353)
- qemu_domain: Add missing IOMMUFD cleanup (RHEL-150353)
- qemu_process: Fix FD leak with multiple host devices using IOMMUFD (RHEL-150353)
- qemu_process: Refactor qemuProcessOpenVfioFds (RHEL-150353)
- qemuxmlconftest: Refactor host device preparation (RHEL-150353)
- qemuxmlconftest: Rename and refactor testSetupHostdevPrivateData (RHEL-150353)
- qemuxmlconftest: Set fake FD for IOMMUFD (RHEL-150353)
- qemu: Convert IOMMUFD to qemuFDPassDirect (RHEL-150353)
- qemu: Convert vfioDeviceFd to qemuFDPassDirect (RHEL-150353)
- qemu_command: Don't use host property if IOMMUFD is used (RHEL-150353)
- qemu: Save IOMMUFD state into status XML (RHEL-150353)
- qemu_hotplug: Remove iommufd object if no longer needed (RHEL-150353)
- qemu_command: Extract building IOMMUFD props to function (RHEL-150353)
- qemu_hotplug: Add support to hotplug host device with IOMMUFD (RHEL-150353)
- conf: Introduce iommufd enum for domaincaps (RHEL-138544)
- qemu: Fill iommufd domain capability (RHEL-138544)
- tests: properly mock VFIO and IOMMU checks (RHEL-138544)
- iommufd: fix FD leak in case of error (RHEL-150353)
* 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-140614)
- qemu: capabilities: Introduce QEMU_CAPS_DEVICE_SCSI_BLOCK_MIGRATE_PR (RHEL-140614)