[libvirt] [PATCH 10/12] virCaps: Introduce IOMMU and VFIO capabilities

Michal Privoznik mprivozn at redhat.com
Thu May 29 08:32:44 UTC 2014


There's no need to check for these two host capabilities on each
device attach or detach. It's sufficient to check them on the daemon
start and then just query them from virCaps when needed. Moreover,
this way it's fairly simple to expose them in capabilities XML.

Signed-off-by: Michal Privoznik <mprivozn at redhat.com>
---
 src/conf/capabilities.c          | 46 ++++++++++++++++++++++++++++++++++++++++
 src/conf/capabilities.h          | 11 ++++++++++
 src/libvirt_private.syms         |  5 +++++
 src/lxc/lxc_conf.c               |  3 +++
 src/nodeinfo.c                   | 15 +++++++++++++
 src/nodeinfo.h                   |  1 +
 src/parallels/parallels_driver.c |  3 +++
 src/phyp/phyp_driver.c           |  3 +++
 src/qemu/qemu_capabilities.c     |  3 +++
 src/qemu/qemu_driver.c           | 16 ++++++++++++--
 src/qemu/qemu_hostdev.c          | 21 ++++++++++++++----
 src/uml/uml_conf.c               |  3 +++
 src/vbox/vbox_tmpl.c             |  3 +++
 13 files changed, 127 insertions(+), 6 deletions(-)

diff --git a/src/conf/capabilities.c b/src/conf/capabilities.c
index cf474d7..9561ba3 100644
--- a/src/conf/capabilities.c
+++ b/src/conf/capabilities.c
@@ -1068,3 +1068,49 @@ virCapabilitiesGetCpusForNodemask(virCapsPtr caps,
 
     return ret;
 }
+
+
+int
+virCapabilitiesGetKVMLegacy(virCapsPtr caps,
+                                bool *legacy)
+{
+    if (!caps)
+        return -1;
+
+    *legacy = caps->host.legacyKVMPassthrough;
+    return 0;
+}
+
+int
+virCapabilitiesSetKVMLegacy(virCapsPtr caps,
+                            bool legacy)
+{
+    if (!caps)
+        return -1;
+
+    caps->host.legacyKVMPassthrough = legacy;
+    return 0;
+}
+
+
+int
+virCapabilitiesGetVFIO(virCapsPtr caps,
+                       bool *vfio)
+{
+    if (!caps)
+        return -1;
+
+    *vfio = caps->host.VFIOPassthrough;
+    return 0;
+}
+
+int
+virCapabilitiesSetVFIO(virCapsPtr caps,
+                       bool vfio)
+{
+    if (!caps)
+        return -1;
+
+    caps->host.VFIOPassthrough = vfio;
+    return 0;
+}
diff --git a/src/conf/capabilities.h b/src/conf/capabilities.h
index ba99e1a..935cd14 100644
--- a/src/conf/capabilities.h
+++ b/src/conf/capabilities.h
@@ -144,6 +144,9 @@ struct _virCapsHost {
 
     virCPUDefPtr cpu;
     unsigned char host_uuid[VIR_UUID_BUFLEN];
+
+    bool legacyKVMPassthrough;
+    bool VFIOPassthrough;
 };
 
 typedef int (*virDomainDefNamespaceParse)(xmlDocPtr, xmlNodePtr,
@@ -274,4 +277,12 @@ virCapabilitiesFormatXML(virCapsPtr caps);
 virBitmapPtr virCapabilitiesGetCpusForNodemask(virCapsPtr caps,
                                                virBitmapPtr nodemask);
 
+int virCapabilitiesGetKVMLegacy(virCapsPtr caps,
+                                bool *legacy);
+int virCapabilitiesSetKVMLegacy(virCapsPtr caps,
+                                bool legacy);
+int virCapabilitiesGetVFIO(virCapsPtr caps,
+                           bool *vfio);
+int virCapabilitiesSetVFIO(virCapsPtr caps,
+                           bool vfio);
 #endif /* __VIR_CAPABILITIES_H */
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 9a942ec..95f1599 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -58,9 +58,13 @@ virCapabilitiesFormatXML;
 virCapabilitiesFreeMachines;
 virCapabilitiesFreeNUMAInfo;
 virCapabilitiesGetCpusForNodemask;
+virCapabilitiesGetKVMLegacy;
+virCapabilitiesGetVFIO;
 virCapabilitiesHostSecModelAddBaseLabel;
 virCapabilitiesNew;
 virCapabilitiesSetHostCPU;
+virCapabilitiesSetKVMLegacy;
+virCapabilitiesSetVFIO;
 
 
 # conf/cpu_conf.h
@@ -866,6 +870,7 @@ virLockManagerRelease;
 
 
 # nodeinfo.h
+nodeCapsInitKVM;
 nodeCapsInitNUMA;
 nodeGetCellsFreeMemory;
 nodeGetCPUBitmap;
diff --git a/src/lxc/lxc_conf.c b/src/lxc/lxc_conf.c
index a35a5e0..9589290 100644
--- a/src/lxc/lxc_conf.c
+++ b/src/lxc/lxc_conf.c
@@ -82,6 +82,9 @@ virCapsPtr virLXCDriverCapsInit(virLXCDriverPtr driver)
         VIR_WARN("Failed to query host NUMA topology, disabling NUMA capabilities");
     }
 
+    if (nodeCapsInitKVM(caps) < 0)
+        VIR_WARN("Failed to query KVM info");
+
     if (virNodeSuspendGetTargetMask(&caps->host.powerMgmt) < 0)
         VIR_WARN("Failed to get host power management capabilities");
 
diff --git a/src/nodeinfo.c b/src/nodeinfo.c
index be63a30..d5ce75b 100644
--- a/src/nodeinfo.c
+++ b/src/nodeinfo.c
@@ -52,6 +52,7 @@
 #include "virtypedparam.h"
 #include "virstring.h"
 #include "virnuma.h"
+#include "virhostdev.h"
 
 #define VIR_FROM_THIS VIR_FROM_NONE
 
@@ -1821,6 +1822,20 @@ nodeCapsInitNUMA(virCapsPtr caps)
 
 
 int
+nodeCapsInitKVM(virCapsPtr caps)
+{
+    bool legacy = virHostdevHostSupportsPassthroughLegacy();
+    bool vfio = virHostdevHostSupportsPassthroughVFIO();
+
+    if (virCapabilitiesSetKVMLegacy(caps, legacy) < 0 ||
+        virCapabilitiesSetVFIO(caps, vfio) < 0)
+        return -1;
+
+    return 0;
+}
+
+
+int
 nodeGetCellsFreeMemory(unsigned long long *freeMems,
                        int startCell,
                        int maxCells)
diff --git a/src/nodeinfo.h b/src/nodeinfo.h
index 625de39..52d74fc 100644
--- a/src/nodeinfo.h
+++ b/src/nodeinfo.h
@@ -28,6 +28,7 @@
 
 int nodeGetInfo(virNodeInfoPtr nodeinfo);
 int nodeCapsInitNUMA(virCapsPtr caps);
+int nodeCapsInitKVM(virCapsPtr caps);
 
 int nodeGetCPUStats(int cpuNum,
                     virNodeCPUStatsPtr params,
diff --git a/src/parallels/parallels_driver.c b/src/parallels/parallels_driver.c
index ab59599..9bd7bef 100644
--- a/src/parallels/parallels_driver.c
+++ b/src/parallels/parallels_driver.c
@@ -126,6 +126,9 @@ parallelsBuildCapabilities(void)
     if (nodeCapsInitNUMA(caps) < 0)
         goto error;
 
+    if (nodeCapsInitKVM(caps) < 0)
+        VIR_WARN("Failed to query KVM info");
+
     if ((guest = virCapabilitiesAddGuest(caps, "hvm",
                                          VIR_ARCH_X86_64,
                                          "parallels",
diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c
index 508e4c0..43e3aea 100644
--- a/src/phyp/phyp_driver.c
+++ b/src/phyp/phyp_driver.c
@@ -305,6 +305,9 @@ phypCapsInit(void)
             ("Failed to query host NUMA topology, disabling NUMA capabilities");
     }
 
+    if (nodeCapsInitKVM(caps) < 0)
+        VIR_WARN("Failed to query KVM info");
+
     if ((guest = virCapabilitiesAddGuest(caps,
                                          "linux",
                                          caps->host.arch,
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index 08c3d04..89f38e2 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -939,6 +939,9 @@ virCapsPtr virQEMUCapsInit(virQEMUCapsCachePtr cache)
         VIR_WARN("Failed to query host NUMA topology, disabling NUMA capabilities");
     }
 
+    if (nodeCapsInitKVM(caps) < 0)
+        VIR_WARN("Failed to query KVM info");
+
     if (virQEMUCapsInitCPU(caps, hostarch) < 0)
         VIR_WARN("Failed to get host CPU");
 
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index d8d0e89..9f97b56 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -11313,12 +11313,23 @@ qemuNodeDeviceDetachFlags(virNodeDevicePtr dev,
     int ret = -1;
     virNodeDeviceDefPtr def = NULL;
     char *xml = NULL;
-    bool legacy = virHostdevHostSupportsPassthroughLegacy();
-    bool vfio = virHostdevHostSupportsPassthroughVFIO();
+    virCapsPtr caps = NULL;
+    bool legacy;
+    bool vfio;
     virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr;
 
     virCheckFlags(0, -1);
 
+    if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
+        goto cleanup;
+
+    if (virCapabilitiesGetKVMLegacy(caps, &legacy) < 0 ||
+        virCapabilitiesGetVFIO(caps, &vfio) < 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("Unable to get info on KVM of VFIO"));
+        goto cleanup;
+    }
+
     xml = virNodeDeviceGetXMLDesc(dev, 0);
     if (!xml)
         goto cleanup;
@@ -11379,6 +11390,7 @@ qemuNodeDeviceDetachFlags(virNodeDevicePtr dev,
     virPCIDeviceFree(pci);
     virNodeDeviceDefFree(def);
     VIR_FREE(xml);
+    virObjectUnref(caps);
     return ret;
 }
 
diff --git a/src/qemu/qemu_hostdev.c b/src/qemu/qemu_hostdev.c
index 39dacb2..1b2ae95 100644
--- a/src/qemu/qemu_hostdev.c
+++ b/src/qemu/qemu_hostdev.c
@@ -84,14 +84,22 @@ qemuUpdateActiveSCSIHostdevs(virQEMUDriverPtr driver,
 
 
 static bool
-qemuPrepareHostdevPCICheckSupport(virDomainHostdevDefPtr *hostdevs,
+qemuPrepareHostdevPCICheckSupport(virCapsPtr caps,
+                                  virDomainHostdevDefPtr *hostdevs,
                                   size_t nhostdevs,
                                   virQEMUCapsPtr qemuCaps)
 {
-    bool supportsPassthroughKVM = virHostdevHostSupportsPassthroughLegacy();
-    bool supportsPassthroughVFIO = virHostdevHostSupportsPassthroughVFIO();
+    bool supportsPassthroughKVM;
+    bool supportsPassthroughVFIO;
     size_t i;
 
+    if (virCapabilitiesGetKVMLegacy(caps, &supportsPassthroughKVM) < 0 ||
+        virCapabilitiesGetVFIO(caps, &supportsPassthroughVFIO) < 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("Unable to get info on KVM of VFIO"));
+        return false;
+    }
+
     /* assign defaults for hostdev passthrough */
     for (i = 0; i < nhostdevs; i++) {
         virDomainHostdevDefPtr hostdev = hostdevs[i];
@@ -156,15 +164,20 @@ qemuPrepareHostdevPCIDevices(virQEMUDriverPtr driver,
                              unsigned int flags)
 {
     int ret = -1;
+    virCapsPtr caps = NULL;
     virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr;
 
-    if (!qemuPrepareHostdevPCICheckSupport(hostdevs, nhostdevs, qemuCaps))
+    if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
+        goto out;
+
+    if (!qemuPrepareHostdevPCICheckSupport(caps, hostdevs, nhostdevs, qemuCaps))
         goto out;
 
     ret = virHostdevPreparePCIDevices(hostdev_mgr, QEMU_DRIVER_NAME,
                                       name, uuid, hostdevs,
                                       nhostdevs, flags);
  out:
+    virObjectUnref(caps);
     return ret;
 }
 
diff --git a/src/uml/uml_conf.c b/src/uml/uml_conf.c
index 464d56d..6fa0546 100644
--- a/src/uml/uml_conf.c
+++ b/src/uml/uml_conf.c
@@ -70,6 +70,9 @@ virCapsPtr umlCapsInit(void)
         VIR_WARN("Failed to query host NUMA topology, disabling NUMA capabilities");
     }
 
+    if (nodeCapsInitKVM(caps) < 0)
+        VIR_WARN("Failed to query KVM info");
+
     if (virNodeSuspendGetTargetMask(&caps->host.powerMgmt) < 0)
         VIR_WARN("Failed to get host power management capabilities");
 
diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c
index e124e69..5a4e170 100644
--- a/src/vbox/vbox_tmpl.c
+++ b/src/vbox/vbox_tmpl.c
@@ -888,6 +888,9 @@ static virCapsPtr vboxCapsInit(void)
     if (nodeCapsInitNUMA(caps) < 0)
         goto no_memory;
 
+    if (nodeCapsInitKVM(caps) < 0)
+        VIR_WARN("Failed to query KVM info");
+
     if ((guest = virCapabilitiesAddGuest(caps,
                                          "hvm",
                                          caps->host.arch,
-- 
1.9.3




More information about the libvir-list mailing list