[PATCH] qemu: Support vhost-vdpa-device.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



    Since 8.0 version, qemu introduced a new device of
    'vhost-vdpa-device-pci' that does not differentiate specific virtio
    devices, which called generic vDPA device.

    The generic vDPA solution avoids the need for maintaining a large amount of
    device emulation code, reducing maintenance costs..

    the device configured as follows:
        <gvdpa>
            <source dev='/dev/vhost-vdpa-0'/>
        </gvdpa>

Signed-off-by: Yunfeng Qi <yunfeng.qi@xxxxxxxxxxxxxxx>
---
 docs/formatdomain.rst                         |  17 +++
 src/ch/ch_domain.c                            |   1 +
 src/conf/domain_conf.c                        | 106 ++++++++++++++++++
 src/conf/domain_conf.h                        |  12 ++
 src/conf/domain_postparse.c                   |   1 +
 src/conf/domain_validate.c                    |  11 ++
 src/conf/schemas/domaincommon.rng             |  23 ++++
 src/conf/virconftypes.h                       |   2 +
 src/hyperv/hyperv_driver.c                    |   1 +
 src/libxl/libxl_driver.c                      |   6 +
 src/lxc/lxc_driver.c                          |   6 +
 src/qemu/qemu_alias.c                         |  21 ++++
 src/qemu/qemu_cgroup.c                        |   6 +
 src/qemu/qemu_command.c                       |  55 +++++++++
 src/qemu/qemu_domain.c                        |   3 +
 src/qemu/qemu_domain_address.c                |  13 +++
 src/qemu/qemu_driver.c                        |   3 +
 src/qemu/qemu_hotplug.c                       |   5 +
 src/qemu/qemu_validate.c                      |  12 ++
 src/vz/vz_sdk.c                               |   3 +
 .../generic-vdpa.x86_64-latest.args           |  34 ++++++
 .../generic-vdpa.x86_64-latest.xml            |   1 +
 tests/qemuxmlconfdata/generic-vdpa.xml        |  43 +++++++
 tests/qemuxmlconftest.c                       |   1 +
 24 files changed, 386 insertions(+)
 create mode 100644 tests/qemuxmlconfdata/generic-vdpa.x86_64-latest.args
 create mode 120000 tests/qemuxmlconfdata/generic-vdpa.x86_64-latest.xml
 create mode 100644 tests/qemuxmlconfdata/generic-vdpa.xml

diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst
index 2adc2ff..182987b 100644
--- a/docs/formatdomain.rst
+++ b/docs/formatdomain.rst
@@ -8622,6 +8622,23 @@ The optional attribute ``backend`` is required if the ``type`` is ``qemu``, the
    ...
 
 
+GVdpa
+~~~~~~
+
+A generic vdpa device.
+The attribute ``dev`` is required and specifies the path of the generic vdpa device.
+
+::
+
+   ...
+   <devices>
+     <gvdpa>
+       <source dev='/dev/vhost-vdpa-0'/>
+     </gvdpa>
+   </devices>
+   ...
+
+
 Security label
 --------------
 
diff --git a/src/ch/ch_domain.c b/src/ch/ch_domain.c
index 8e3e205..f9fbad6 100644
--- a/src/ch/ch_domain.c
+++ b/src/ch/ch_domain.c
@@ -180,6 +180,7 @@ chValidateDomainDeviceDef(const virDomainDeviceDef *dev,
     case VIR_DOMAIN_DEVICE_IOMMU:
     case VIR_DOMAIN_DEVICE_AUDIO:
     case VIR_DOMAIN_DEVICE_CRYPTO:
+    case VIR_DOMAIN_DEVICE_GVDPA:
         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                        _("Cloud-Hypervisor doesn't support '%1$s' device"),
                        virDomainDeviceTypeToString(dev->type));
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 770b5fb..100d112 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -336,6 +336,7 @@ VIR_ENUM_IMPL(virDomainDevice,
               "vsock",
               "audio",
               "crypto",
+              "gvdpa"
 );
 
 VIR_ENUM_IMPL(virDomainDiskDevice,
@@ -3627,6 +3628,9 @@ void virDomainDeviceDefFree(virDomainDeviceDef *def)
     case VIR_DOMAIN_DEVICE_CRYPTO:
         virDomainCryptoDefFree(def->data.crypto);
         break;
+    case VIR_DOMAIN_DEVICE_GVDPA:
+        virDomainGVdpaDefFree(def->data.gvdpa);
+        break;
     case VIR_DOMAIN_DEVICE_LAST:
     case VIR_DOMAIN_DEVICE_NONE:
         break;
@@ -3984,6 +3988,10 @@ void virDomainDefFree(virDomainDef *def)
         virDomainCryptoDefFree(def->cryptos[i]);
     g_free(def->cryptos);
 
+    for (i = 0; i < def->ngvdpas; i++)
+        virDomainGVdpaDefFree(def->gvdpas[i]);
+    g_free(def->gvdpas);
+
     virDomainIOMMUDefFree(def->iommu);
 
     g_free(def->idmap.uidmap);
@@ -4543,6 +4551,8 @@ virDomainDeviceGetInfo(const virDomainDeviceDef *device)
         return &device->data.vsock->info;
     case VIR_DOMAIN_DEVICE_CRYPTO:
         return &device->data.crypto->info;
+    case VIR_DOMAIN_DEVICE_GVDPA:
+        return &device->data.gvdpa->info;
 
     /* The following devices do not contain virDomainDeviceInfo */
     case VIR_DOMAIN_DEVICE_LEASE:
@@ -4648,6 +4658,9 @@ virDomainDeviceSetData(virDomainDeviceDef *device,
     case VIR_DOMAIN_DEVICE_CRYPTO:
         device->data.crypto = devicedata;
         break;
+    case VIR_DOMAIN_DEVICE_GVDPA:
+        device->data.gvdpa = devicedata;
+        break;
     case VIR_DOMAIN_DEVICE_NONE:
     case VIR_DOMAIN_DEVICE_LAST:
         break;
@@ -4866,6 +4879,13 @@ virDomainDeviceInfoIterateFlags(virDomainDef *def,
             return rc;
     }
 
+    device.type = VIR_DOMAIN_DEVICE_GVDPA;
+    for (i = 0; i < def->ngvdpas; i++) {
+        device.data.gvdpa = def->gvdpas[i];
+        if ((rc = cb(def, &device, &def->gvdpas[i]->info, opaque)) != 0)
+            return rc;
+    }
+
     /* If the flag below is set, make sure @cb can handle @info being NULL */
     if (iteratorFlags & DOMAIN_DEVICE_ITERATE_MISSING_INFO) {
         device.type = VIR_DOMAIN_DEVICE_GRAPHICS;
@@ -4925,6 +4945,7 @@ virDomainDeviceInfoIterateFlags(virDomainDef *def,
     case VIR_DOMAIN_DEVICE_VSOCK:
     case VIR_DOMAIN_DEVICE_AUDIO:
     case VIR_DOMAIN_DEVICE_CRYPTO:
+    case VIR_DOMAIN_DEVICE_GVDPA:
         break;
     }
 #endif
@@ -13892,6 +13913,41 @@ virDomainCryptoDefParseXML(virDomainXMLOption *xmlopt,
     return g_steal_pointer(&def);
 }
 
+static virDomainGVdpaDef *
+virDomainGVdpaDefParseXML(virDomainXMLOption *xmlopt,
+                           xmlNodePtr node,
+                           xmlXPathContextPtr ctxt,
+                           unsigned int flags)
+{
+    g_autoptr(virDomainGVdpaDef) def = NULL;
+    int nsources;
+    g_autofree xmlNodePtr *sources = NULL;
+    VIR_XPATH_NODE_AUTORESTORE(ctxt)
+
+    def = g_new0(virDomainGVdpaDef, 1);
+    ctxt->node = node;
+
+    if ((nsources = virXPathNodeSet("./source", ctxt, &sources)) < 0)
+        return NULL;
+
+    if (nsources != 1) {
+        virReportError(VIR_ERR_XML_ERROR, "%s",
+                       _("only one gvdpa source is supported"));
+        return NULL;
+    }
+
+    if (!(def->dev = virXMLPropString(sources[0], "dev"))) {
+        virReportError(VIR_ERR_XML_ERROR, "%s",
+                       _("missing dev element"));
+        return NULL;
+    }
+
+    if (virDomainDeviceInfoParseXML(xmlopt, node, ctxt, &def->info, flags | VIR_DOMAIN_DEF_PARSE_ALLOW_BOOT) < 0)
+        return NULL;
+
+    return g_steal_pointer(&def);
+}
+
 
 static int
 virDomainDeviceDefParseType(const char *typestr,
@@ -14072,6 +14128,11 @@ virDomainDeviceDefParse(const char *xmlStr,
                                                             flags)))
             return NULL;
         break;
+    case VIR_DOMAIN_DEVICE_GVDPA:
+        if (!(dev->data.gvdpa = virDomainGVdpaDefParseXML(xmlopt, node, ctxt,
+                                                            flags)))
+            return NULL;
+        break;
     case VIR_DOMAIN_DEVICE_NONE:
     case VIR_DOMAIN_DEVICE_LAST:
         break;
@@ -19230,6 +19291,21 @@ virDomainDefParseXML(xmlXPathContextPtr ctxt,
     }
     VIR_FREE(nodes);
 
+    /* Parse the gvdpa devices */
+    if ((n = virXPathNodeSet("./devices/gvdpa", ctxt, &nodes)) < 0)
+        return NULL;
+    if (n)
+        def->gvdpas = g_new0(virDomainGVdpaDef *, n);
+    for (i = 0; i < n; i++) {
+        virDomainGVdpaDef *gvdpa = virDomainGVdpaDefParseXML(xmlopt, nodes[i],
+                                                                ctxt, flags);
+        if (!gvdpa)
+            return NULL;
+
+        def->gvdpas[def->ngvdpas++] = gvdpa;
+    }
+    VIR_FREE(nodes);
+
     /* Parse the TPM devices */
     if ((n = virXPathNodeSet("./devices/tpm", ctxt, &nodes)) < 0)
         return NULL;
@@ -21788,6 +21864,7 @@ virDomainDefCheckABIStabilityFlags(virDomainDef *src,
     case VIR_DOMAIN_DEVICE_VSOCK:
     case VIR_DOMAIN_DEVICE_AUDIO:
     case VIR_DOMAIN_DEVICE_CRYPTO:
+    case VIR_DOMAIN_DEVICE_GVDPA:
         break;
     }
 #endif
@@ -25334,6 +25411,22 @@ virDomainCryptoDefFormat(virBuffer *buf,
     virXMLFormatElement(buf, "crypto", &attrBuf, &childBuf);
 }
 
+static void
+virDomainGVdpaDefFormat(virBuffer *buf,
+                         virDomainGVdpaDef *def,
+                         unsigned int flags)
+{
+    virBufferAddLit(buf, "<gvdpa>\n");
+
+    virBufferAdjustIndent(buf, 2);
+    virBufferAsprintf(buf, "<source dev='%s'/>\n", def->dev);
+    virDomainDeviceInfoFormat(buf, &def->info, flags | VIR_DOMAIN_DEF_FORMAT_ALLOW_BOOT);
+
+    virBufferAdjustIndent(buf, -2);
+    virBufferAddLit(buf, "</gvdpa>\n");
+}
+
+
 void
 virDomainCryptoDefFree(virDomainCryptoDef *def)
 {
@@ -25345,6 +25438,16 @@ virDomainCryptoDefFree(virDomainCryptoDef *def)
     g_free(def);
 }
 
+void
+virDomainGVdpaDefFree(virDomainGVdpaDef *def)
+{
+    if (!def)
+        return;
+
+    virDomainDeviceInfoClear(&def->info);
+    g_free(def->dev);
+    g_free(def);
+}
 
 static int
 virDomainMemorySourceDefFormat(virBuffer *buf,
@@ -28139,6 +28242,9 @@ virDomainDefFormatInternalSetRootName(virDomainDef *def,
     for (n = 0; n < def->ncryptos; n++) {
         virDomainCryptoDefFormat(buf, def->cryptos[n], flags);
     }
+    for (n = 0; n < def->ngvdpas; n++) {
+        virDomainGVdpaDefFormat(buf, def->gvdpas[n], flags);
+    }
     if (def->iommu)
         virDomainIOMMUDefFormat(buf, def->iommu);
 
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 7625193..a0c94af 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -87,6 +87,7 @@ typedef enum {
     VIR_DOMAIN_DEVICE_VSOCK,
     VIR_DOMAIN_DEVICE_AUDIO,
     VIR_DOMAIN_DEVICE_CRYPTO,
+    VIR_DOMAIN_DEVICE_GVDPA,
 
     VIR_DOMAIN_DEVICE_LAST
 } virDomainDeviceType;
@@ -120,6 +121,7 @@ struct _virDomainDeviceDef {
         virDomainVsockDef *vsock;
         virDomainAudioDef *audio;
         virDomainCryptoDef *crypto;
+        virDomainGVdpaDef *gvdpa;
     } data;
 };
 
@@ -2943,6 +2945,11 @@ struct _virDomainCryptoDef {
     virDomainVirtioOptions *virtio;
 };
 
+struct _virDomainGVdpaDef {
+    char *dev;
+    virDomainDeviceInfo info;
+};
+
 struct _virDomainVirtioOptions {
     virTristateSwitch iommu;
     virTristateSwitch ats;
@@ -3112,6 +3119,9 @@ struct _virDomainDef {
     size_t ncryptos;
     virDomainCryptoDef **cryptos;
 
+    size_t ngvdpas;
+    virDomainGVdpaDef **gvdpas;
+
     size_t nwatchdogs;
     virDomainWatchdogDef **watchdogs;
 
@@ -3569,6 +3579,8 @@ void virDomainVsockDefFree(virDomainVsockDef *vsock);
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(virDomainVsockDef, virDomainVsockDefFree);
 void virDomainCryptoDefFree(virDomainCryptoDef *def);
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(virDomainCryptoDef, virDomainCryptoDefFree);
+void virDomainGVdpaDefFree(virDomainGVdpaDef *def);
+G_DEFINE_AUTOPTR_CLEANUP_FUNC(virDomainGVdpaDef, virDomainGVdpaDefFree);
 void virDomainNetTeamingInfoFree(virDomainNetTeamingInfo *teaming);
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(virDomainNetTeamingInfo, virDomainNetTeamingInfoFree);
 void virDomainNetPortForwardFree(virDomainNetPortForward *pf);
diff --git a/src/conf/domain_postparse.c b/src/conf/domain_postparse.c
index cafa2d2..5a568e8 100644
--- a/src/conf/domain_postparse.c
+++ b/src/conf/domain_postparse.c
@@ -746,6 +746,7 @@ virDomainDeviceDefPostParseCommon(virDomainDeviceDef *dev,
     case VIR_DOMAIN_DEVICE_IOMMU:
     case VIR_DOMAIN_DEVICE_AUDIO:
     case VIR_DOMAIN_DEVICE_CRYPTO:
+    case VIR_DOMAIN_DEVICE_GVDPA:
         ret = 0;
         break;
 
diff --git a/src/conf/domain_validate.c b/src/conf/domain_validate.c
index faa7659..c6729e4 100644
--- a/src/conf/domain_validate.c
+++ b/src/conf/domain_validate.c
@@ -2576,6 +2576,14 @@ virDomainCryptoDefValidate(const virDomainCryptoDef *crypto)
     return 0;
 }
 
+static int
+virDomainGVdpaDefValidate(const virDomainGVdpaDef *gvdpa)
+{
+    if (!gvdpa->dev)
+        return -1;
+
+    return 0;
+}
 
 static int
 virDomainInputDefValidate(const virDomainInputDef *input,
@@ -3058,6 +3066,9 @@ virDomainDeviceDefValidateInternal(const virDomainDeviceDef *dev,
     case VIR_DOMAIN_DEVICE_CRYPTO:
         return virDomainCryptoDefValidate(dev->data.crypto);
 
+    case VIR_DOMAIN_DEVICE_GVDPA:
+        return virDomainGVdpaDefValidate(dev->data.gvdpa);
+
     case VIR_DOMAIN_DEVICE_INPUT:
         return virDomainInputDefValidate(dev->data.input, def);
 
diff --git a/src/conf/schemas/domaincommon.rng b/src/conf/schemas/domaincommon.rng
index c992956..c7c7314 100644
--- a/src/conf/schemas/domaincommon.rng
+++ b/src/conf/schemas/domaincommon.rng
@@ -6609,6 +6609,7 @@
             <ref name="shmem"/>
             <ref name="memorydev"/>
             <ref name="crypto"/>
+            <ref name="gvdpa"/>
           </choice>
         </zeroOrMore>
         <zeroOrMore>
@@ -7457,6 +7458,28 @@
   </define>
 
 
+  <define name="gvdpa">
+    <element name="gvdpa">
+      <interleave>
+        <ref name="gvdpa-source"/>
+        <optional>
+          <ref name="alias"/>
+        </optional>
+        <optional>
+          <ref name="address"/>
+        </optional>
+      </interleave>
+    </element>
+  </define>
+
+  <define name="gvdpa-source">
+    <element name="source">
+      <attribute name="dev">
+         <text/>
+      </attribute>
+    </element>
+  </define>
+
   <define name="virtioOptions">
     <optional>
       <attribute name="iommu">
diff --git a/src/conf/virconftypes.h b/src/conf/virconftypes.h
index 0779bc2..924138a 100644
--- a/src/conf/virconftypes.h
+++ b/src/conf/virconftypes.h
@@ -256,6 +256,8 @@ typedef struct _virDomainVsockDef virDomainVsockDef;
 
 typedef struct _virDomainCryptoDef virDomainCryptoDef;
 
+typedef struct _virDomainGVdpaDef virDomainGVdpaDef;
+
 typedef struct _virDomainWatchdogDef virDomainWatchdogDef;
 
 typedef struct _virDomainXMLOption virDomainXMLOption;
diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c
index 414274f..c7e5cce 100644
--- a/src/hyperv/hyperv_driver.c
+++ b/src/hyperv/hyperv_driver.c
@@ -3132,6 +3132,7 @@ hypervDomainAttachDeviceFlags(virDomainPtr domain, const char *xml, unsigned int
     case VIR_DOMAIN_DEVICE_VSOCK:
     case VIR_DOMAIN_DEVICE_AUDIO:
     case VIR_DOMAIN_DEVICE_CRYPTO:
+    case VIR_DOMAIN_DEVICE_GVDPA:
         virReportError(VIR_ERR_INTERNAL_ERROR,
                        _("Attaching devices of type %1$d is not implemented"), dev->type);
         return -1;
diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c
index e42a3dc..1664c33 100644
--- a/src/libxl/libxl_driver.c
+++ b/src/libxl/libxl_driver.c
@@ -3505,6 +3505,7 @@ libxlDomainAttachDeviceLive(libxlDriverPrivate *driver,
         case VIR_DOMAIN_DEVICE_VSOCK:
         case VIR_DOMAIN_DEVICE_AUDIO:
         case VIR_DOMAIN_DEVICE_CRYPTO:
+        case VIR_DOMAIN_DEVICE_GVDPA:
             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                            _("device type '%1$s' cannot be attached"),
                            virDomainDeviceTypeToString(dev->type));
@@ -3613,6 +3614,7 @@ libxlDomainAttachDeviceConfig(virDomainDef *vmdef, virDomainDeviceDef *dev)
         case VIR_DOMAIN_DEVICE_VSOCK:
         case VIR_DOMAIN_DEVICE_AUDIO:
         case VIR_DOMAIN_DEVICE_CRYPTO:
+        case VIR_DOMAIN_DEVICE_GVDPA:
             virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                            _("persistent attach of device is not supported"));
             return -1;
@@ -3981,6 +3983,7 @@ libxlDomainDetachDeviceLive(libxlDriverPrivate *driver,
         case VIR_DOMAIN_DEVICE_VSOCK:
         case VIR_DOMAIN_DEVICE_AUDIO:
         case VIR_DOMAIN_DEVICE_CRYPTO:
+        case VIR_DOMAIN_DEVICE_GVDPA:
             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                            _("device type '%1$s' cannot be detached"),
                            virDomainDeviceTypeToString(dev->type));
@@ -4071,6 +4074,7 @@ libxlDomainDetachDeviceConfig(virDomainDef *vmdef, virDomainDeviceDef *dev)
         case VIR_DOMAIN_DEVICE_VSOCK:
         case VIR_DOMAIN_DEVICE_AUDIO:
         case VIR_DOMAIN_DEVICE_CRYPTO:
+        case VIR_DOMAIN_DEVICE_GVDPA:
             virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                            _("persistent detach of device is not supported"));
             return -1;
@@ -4133,6 +4137,7 @@ libxlDomainUpdateDeviceLive(virDomainObj *vm, virDomainDeviceDef *dev)
         case VIR_DOMAIN_DEVICE_VSOCK:
         case VIR_DOMAIN_DEVICE_AUDIO:
         case VIR_DOMAIN_DEVICE_CRYPTO:
+        case VIR_DOMAIN_DEVICE_GVDPA:
             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                            _("device type '%1$s' cannot be updated"),
                            virDomainDeviceTypeToString(dev->type));
@@ -4195,6 +4200,7 @@ libxlDomainUpdateDeviceConfig(virDomainDef *vmdef, virDomainDeviceDef *dev)
         case VIR_DOMAIN_DEVICE_VSOCK:
         case VIR_DOMAIN_DEVICE_AUDIO:
         case VIR_DOMAIN_DEVICE_CRYPTO:
+        case VIR_DOMAIN_DEVICE_GVDPA:
             virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                            _("persistent update of device is not supported"));
             return -1;
diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c
index 39992bd..7d11529 100644
--- a/src/lxc/lxc_driver.c
+++ b/src/lxc/lxc_driver.c
@@ -3054,6 +3054,7 @@ lxcDomainAttachDeviceConfig(virDomainDef *vmdef,
     case VIR_DOMAIN_DEVICE_VSOCK:
     case VIR_DOMAIN_DEVICE_AUDIO:
     case VIR_DOMAIN_DEVICE_CRYPTO:
+    case VIR_DOMAIN_DEVICE_GVDPA:
          virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                         _("persistent attach of device is not supported"));
          break;
@@ -3119,6 +3120,7 @@ lxcDomainUpdateDeviceConfig(virDomainDef *vmdef,
     case VIR_DOMAIN_DEVICE_VSOCK:
     case VIR_DOMAIN_DEVICE_AUDIO:
     case VIR_DOMAIN_DEVICE_CRYPTO:
+    case VIR_DOMAIN_DEVICE_GVDPA:
         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                        _("persistent update of device is not supported"));
         break;
@@ -3199,6 +3201,7 @@ lxcDomainDetachDeviceConfig(virDomainDef *vmdef,
     case VIR_DOMAIN_DEVICE_IOMMU:
     case VIR_DOMAIN_DEVICE_VSOCK:
     case VIR_DOMAIN_DEVICE_CRYPTO:
+    case VIR_DOMAIN_DEVICE_GVDPA:
     case VIR_DOMAIN_DEVICE_AUDIO:
         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                        _("persistent detach of device is not supported"));
@@ -3301,6 +3304,7 @@ lxcDomainAttachDeviceMknodHelper(pid_t pid G_GNUC_UNUSED,
     case VIR_DOMAIN_DEVICE_VSOCK:
     case VIR_DOMAIN_DEVICE_AUDIO:
     case VIR_DOMAIN_DEVICE_CRYPTO:
+    case VIR_DOMAIN_DEVICE_GVDPA:
         virReportError(VIR_ERR_INTERNAL_ERROR,
                        _("Unexpected device type %1$d"),
                        data->def->type);
@@ -3972,6 +3976,7 @@ lxcDomainAttachDeviceLive(virLXCDriver *driver,
     case VIR_DOMAIN_DEVICE_VSOCK:
     case VIR_DOMAIN_DEVICE_AUDIO:
     case VIR_DOMAIN_DEVICE_CRYPTO:
+    case VIR_DOMAIN_DEVICE_GVDPA:
         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                        _("device type '%1$s' cannot be attached"),
                        virDomainDeviceTypeToString(dev->type));
@@ -4396,6 +4401,7 @@ lxcDomainDetachDeviceLive(virLXCDriver *driver,
     case VIR_DOMAIN_DEVICE_VSOCK:
     case VIR_DOMAIN_DEVICE_AUDIO:
     case VIR_DOMAIN_DEVICE_CRYPTO:
+    case VIR_DOMAIN_DEVICE_GVDPA:
         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                        _("device type '%1$s' cannot be detached"),
                        virDomainDeviceTypeToString(dev->type));
diff --git a/src/qemu/qemu_alias.c b/src/qemu/qemu_alias.c
index 872d940..518abd3 100644
--- a/src/qemu/qemu_alias.c
+++ b/src/qemu/qemu_alias.c
@@ -657,6 +657,24 @@ qemuAssignDeviceCryptoAlias(virDomainDef *def,
     crypto->info.alias = g_strdup_printf("crypto%d", maxidx);
 }
 
+static void
+qemuAssignDeviceGVdpaAlias(virDomainDef *def,
+                            virDomainGVdpaDef *gvdpa)
+{
+    size_t i;
+    int maxidx = 0;
+    int idx;
+
+    if (gvdpa->info.alias)
+        return;
+
+    for (i = 0; i < def->ngvdpas; i++) {
+        if ((idx = qemuDomainDeviceAliasIndex(&def->gvdpas[i]->info, "gvdpa")) >= maxidx)
+            maxidx = idx + 1;
+    }
+
+    gvdpa->info.alias = g_strdup_printf("gvdpa%d", maxidx);
+}
 
 int
 qemuAssignDeviceAliases(virDomainDef *def)
@@ -747,6 +765,9 @@ qemuAssignDeviceAliases(virDomainDef *def)
     for (i = 0; i < def->ncryptos; i++) {
         qemuAssignDeviceCryptoAlias(def, def->cryptos[i]);
     }
+    for (i = 0; i < def->ngvdpas; i++) {
+        qemuAssignDeviceGVdpaAlias(def, def->gvdpas[i]);
+    }
 
     return 0;
 }
diff --git a/src/qemu/qemu_cgroup.c b/src/qemu/qemu_cgroup.c
index 5a5ba76..1206359 100644
--- a/src/qemu/qemu_cgroup.c
+++ b/src/qemu/qemu_cgroup.c
@@ -845,6 +845,12 @@ qemuSetupDevicesCgroup(virDomainObj *vm)
             return -1;
     }
 
+    for (i = 0; i < vm->def->ngvdpas; i++) {
+        if (qemuCgroupAllowDevicePath(vm, vm->def->gvdpas[i]->dev,
+				    VIR_CGROUP_DEVICE_RW, false) < 0)
+        return -1;
+    }
+
     if (vm->def->sec &&
         vm->def->sec->sectype == VIR_DOMAIN_LAUNCH_SECURITY_SEV &&
         qemuSetupSEVCgroup(vm) < 0)
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 2bb1b6a..faf96f9 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -969,6 +969,7 @@ qemuBuildVirtioDevGetConfigDev(const virDomainDeviceDef *device,
         case VIR_DOMAIN_DEVICE_IOMMU:
         case VIR_DOMAIN_DEVICE_AUDIO:
         case VIR_DOMAIN_DEVICE_LAST:
+        case VIR_DOMAIN_DEVICE_GVDPA:
         default:
             break;
     }
@@ -10254,6 +10255,57 @@ qemuBuildCryptoCommandLine(virCommand *cmd,
     return 0;
 }
 
+static virJSONValue *
+qemuBuildGVdpaDevProps(const virDomainDef *def,
+                        virDomainGVdpaDef *dev)
+{
+    g_autoptr(virJSONValue) props = NULL;
+
+    if (virJSONValueObjectAdd(&props,
+                              "s:driver", "vhost-vdpa-device-pci",
+                              "s:vhostdev", dev->dev,
+                              "s:id", dev->info.alias,
+                              "p:bootindex", dev->info.effectiveBootIndex,
+                              NULL) < 0)
+        return NULL;
+
+    if (qemuBuildDeviceAddressProps(props, def, &dev->info) < 0)
+        return NULL;
+
+    return g_steal_pointer(&props);
+}
+
+static int
+qemuBuildGVdpaCommandLine(virCommand *cmd,
+                           const virDomainDef *def,
+                           virQEMUCaps *qemuCaps)
+{
+    size_t i;
+
+    for (i = 0; i < def->ngvdpas; i++) {
+        virDomainGVdpaDef *gvdpa = def->gvdpas[i];
+        g_autoptr(virJSONValue) devprops = NULL;
+
+        if (!gvdpa->info.alias) {
+            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                           _("GVdpa device is missing alias"));
+            return -1;
+        }
+
+        /* add the device */
+        if (qemuCommandAddExtDevice(cmd, &gvdpa->info, def, qemuCaps) < 0)
+            return -1;
+
+        if (!(devprops = qemuBuildGVdpaDevProps(def, gvdpa)))
+            return -1;
+
+        if (qemuBuildDeviceCommandlineFromJSON(cmd, devprops, def, qemuCaps) < 0)
+            return -1;
+    }
+
+    return 0;
+}
+
 
 static int
 qemuBuildAsyncTeardownCommandLine(virCommand *cmd,
@@ -10628,6 +10680,9 @@ qemuBuildCommandLine(virDomainObj *vm,
     if (qemuBuildCryptoCommandLine(cmd, def, qemuCaps) < 0)
         return NULL;
 
+    if (qemuBuildGVdpaCommandLine(cmd, def, qemuCaps) < 0)
+        return NULL;
+
     if (qemuBuildAsyncTeardownCommandLine(cmd, def, qemuCaps) < 0)
         return NULL;
 
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index bc6cf13..132b479 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -6324,6 +6324,7 @@ qemuDomainDeviceDefPostParse(virDomainDeviceDef *dev,
     case VIR_DOMAIN_DEVICE_IOMMU:
     case VIR_DOMAIN_DEVICE_AUDIO:
     case VIR_DOMAIN_DEVICE_CRYPTO:
+    case VIR_DOMAIN_DEVICE_GVDPA:
         ret = 0;
         break;
 
@@ -10301,6 +10302,7 @@ qemuDomainPrepareChardevSourceOne(virDomainDeviceDef *dev,
     case VIR_DOMAIN_DEVICE_VSOCK:
     case VIR_DOMAIN_DEVICE_AUDIO:
     case VIR_DOMAIN_DEVICE_CRYPTO:
+    case VIR_DOMAIN_DEVICE_GVDPA:
         break;
     }
 
@@ -12232,6 +12234,7 @@ qemuDomainDeviceBackendChardevForeachOne(virDomainDeviceDef *dev,
     case VIR_DOMAIN_DEVICE_VSOCK:
     case VIR_DOMAIN_DEVICE_AUDIO:
     case VIR_DOMAIN_DEVICE_CRYPTO:
+    case VIR_DOMAIN_DEVICE_GVDPA:
         /* no chardev backend */
         break;
     }
diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c
index cc3bc76..5db2dfa 100644
--- a/src/qemu/qemu_domain_address.c
+++ b/src/qemu/qemu_domain_address.c
@@ -464,6 +464,7 @@ qemuDomainDeviceSupportZPCI(virDomainDeviceDef *device)
     case VIR_DOMAIN_DEVICE_VSOCK:
     case VIR_DOMAIN_DEVICE_AUDIO:
     case VIR_DOMAIN_DEVICE_CRYPTO:
+    case VIR_DOMAIN_DEVICE_GVDPA:
         break;
 
     case VIR_DOMAIN_DEVICE_NONE:
@@ -978,6 +979,9 @@ qemuDomainDeviceCalculatePCIConnectFlags(virDomainDeviceDef *dev,
         }
         break;
 
+    case VIR_DOMAIN_DEVICE_GVDPA:
+        return pciFlags;
+
     case VIR_DOMAIN_DEVICE_PANIC:
         switch ((virDomainPanicModel) dev->data.panic->model) {
         case VIR_DOMAIN_PANIC_MODEL_PVPANIC:
@@ -2392,6 +2396,15 @@ qemuDomainAssignDevicePCISlots(virDomainDef *def,
             return -1;
     }
 
+    /* gvdpa */
+    for (i = 0; i < def->ngvdpas; i++) {
+        if (!virDeviceInfoPCIAddressIsWanted(&def->gvdpas[i]->info))
+            continue;
+
+        if (qemuDomainPCIAddressReserveNextAddr(addrs, &def->gvdpas[i]->info) < 0)
+            return -1;
+    }
+
     for (i = 0; i < def->npanics; i++) {
         virDomainPanicDef *panic = def->panics[i];
 
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index d01f788..5e3ea85 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -6859,6 +6859,7 @@ qemuDomainAttachDeviceConfig(virDomainDef *vmdef,
     case VIR_DOMAIN_DEVICE_IOMMU:
     case VIR_DOMAIN_DEVICE_AUDIO:
     case VIR_DOMAIN_DEVICE_CRYPTO:
+    case VIR_DOMAIN_DEVICE_GVDPA:
     case VIR_DOMAIN_DEVICE_LAST:
          virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
                         _("persistent attach of device '%1$s' is not supported"),
@@ -7066,6 +7067,7 @@ qemuDomainDetachDeviceConfig(virDomainDef *vmdef,
     case VIR_DOMAIN_DEVICE_IOMMU:
     case VIR_DOMAIN_DEVICE_AUDIO:
     case VIR_DOMAIN_DEVICE_CRYPTO:
+    case VIR_DOMAIN_DEVICE_GVDPA:
     case VIR_DOMAIN_DEVICE_LAST:
         virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
                        _("persistent detach of device '%1$s' is not supported"),
@@ -7191,6 +7193,7 @@ qemuDomainUpdateDeviceConfig(virDomainDef *vmdef,
     case VIR_DOMAIN_DEVICE_VSOCK:
     case VIR_DOMAIN_DEVICE_AUDIO:
     case VIR_DOMAIN_DEVICE_CRYPTO:
+    case VIR_DOMAIN_DEVICE_GVDPA:
     case VIR_DOMAIN_DEVICE_LAST:
         virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
                        _("persistent update of device '%1$s' is not supported"),
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index b9c5026..dc9caec 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -3454,6 +3454,7 @@ qemuDomainAttachDeviceLive(virDomainObj *vm,
     case VIR_DOMAIN_DEVICE_IOMMU:
     case VIR_DOMAIN_DEVICE_AUDIO:
     case VIR_DOMAIN_DEVICE_CRYPTO:
+    case VIR_DOMAIN_DEVICE_GVDPA:
     case VIR_DOMAIN_DEVICE_LAST:
         virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
                        _("live attach of device '%1$s' is not supported"),
@@ -5281,6 +5282,7 @@ qemuDomainRemoveAuditDevice(virDomainObj *vm,
     case VIR_DOMAIN_DEVICE_IOMMU:
     case VIR_DOMAIN_DEVICE_AUDIO:
     case VIR_DOMAIN_DEVICE_CRYPTO:
+    case VIR_DOMAIN_DEVICE_GVDPA:
     case VIR_DOMAIN_DEVICE_LAST:
         /* libvirt doesn't yet support detaching these devices */
         break;
@@ -5385,6 +5387,7 @@ qemuDomainRemoveDevice(virQEMUDriver *driver,
     case VIR_DOMAIN_DEVICE_IOMMU:
     case VIR_DOMAIN_DEVICE_AUDIO:
     case VIR_DOMAIN_DEVICE_CRYPTO:
+    case VIR_DOMAIN_DEVICE_GVDPA:
     case VIR_DOMAIN_DEVICE_LAST:
         virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
                        _("don't know how to remove a %1$s device"),
@@ -6239,6 +6242,7 @@ qemuDomainDetachDeviceLive(virDomainObj *vm,
     case VIR_DOMAIN_DEVICE_IOMMU:
     case VIR_DOMAIN_DEVICE_AUDIO:
     case VIR_DOMAIN_DEVICE_CRYPTO:
+    case VIR_DOMAIN_DEVICE_GVDPA:
     case VIR_DOMAIN_DEVICE_LAST:
         virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
                        _("live detach of device '%1$s' is not supported"),
@@ -7228,6 +7232,7 @@ qemuDomainUpdateDeviceLive(virDomainObj *vm,
     case VIR_DOMAIN_DEVICE_VSOCK:
     case VIR_DOMAIN_DEVICE_AUDIO:
     case VIR_DOMAIN_DEVICE_CRYPTO:
+    case VIR_DOMAIN_DEVICE_GVDPA:
     case VIR_DOMAIN_DEVICE_LAST:
         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                        _("live update of device '%1$s' is not supported"),
diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c
index 6a73d02..964cf5b 100644
--- a/src/qemu/qemu_validate.c
+++ b/src/qemu/qemu_validate.c
@@ -4577,6 +4577,15 @@ qemuValidateDomainDeviceDefCrypto(virDomainCryptoDef *crypto,
     return 0;
 }
 
+static int
+qemuValidateDomainDeviceDefGVdpa(virDomainGVdpaDef *gvdpa G_GNUC_UNUSED,
+                                  const virDomainDef *def G_GNUC_UNUSED,
+                                  virQEMUCaps *qemuCaps G_GNUC_UNUSED)
+{
+    if (qemuValidateDomainDefVhostUserRequireSharedMemory(def, "generic-vdpa") < 0)
+        return -1;
+    return 0;
+}
 
 static int
 qemuSoundCodecTypeToCaps(int type)
@@ -5277,6 +5286,9 @@ qemuValidateDomainDeviceDef(const virDomainDeviceDef *dev,
     case VIR_DOMAIN_DEVICE_CRYPTO:
         return qemuValidateDomainDeviceDefCrypto(dev->data.crypto, def, qemuCaps);
 
+    case VIR_DOMAIN_DEVICE_GVDPA:
+        return qemuValidateDomainDeviceDefGVdpa(dev->data.gvdpa, def, qemuCaps);
+
     case VIR_DOMAIN_DEVICE_LEASE:
     case VIR_DOMAIN_DEVICE_PANIC:
     case VIR_DOMAIN_DEVICE_NONE:
diff --git a/src/vz/vz_sdk.c b/src/vz/vz_sdk.c
index ce4586a..1c1064b 100644
--- a/src/vz/vz_sdk.c
+++ b/src/vz/vz_sdk.c
@@ -3534,6 +3534,7 @@ prlsdkAttachDevice(struct _vzDriver *driver,
     case VIR_DOMAIN_DEVICE_VSOCK:
     case VIR_DOMAIN_DEVICE_AUDIO:
     case VIR_DOMAIN_DEVICE_CRYPTO:
+    case VIR_DOMAIN_DEVICE_GVDPA:
         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                        _("attaching device type '%1$s' is unsupported"),
                        virDomainDeviceTypeToString(dev->type));
@@ -3624,6 +3625,7 @@ prlsdkDetachDevice(struct _vzDriver *driver G_GNUC_UNUSED,
     case VIR_DOMAIN_DEVICE_VSOCK:
     case VIR_DOMAIN_DEVICE_AUDIO:
     case VIR_DOMAIN_DEVICE_CRYPTO:
+    case VIR_DOMAIN_DEVICE_GVDPA:
         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                        _("detaching device type '%1$s' is unsupported"),
                        virDomainDeviceTypeToString(dev->type));
@@ -3704,6 +3706,7 @@ prlsdkUpdateDevice(struct _vzDriver *driver,
     case VIR_DOMAIN_DEVICE_VSOCK:
     case VIR_DOMAIN_DEVICE_AUDIO:
     case VIR_DOMAIN_DEVICE_CRYPTO:
+    case VIR_DOMAIN_DEVICE_GVDPA:
         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                        _("updating device type '%1$s' is unsupported"),
                        virDomainDeviceTypeToString(dev->type));
diff --git a/tests/qemuxmlconfdata/generic-vdpa.x86_64-latest.args b/tests/qemuxmlconfdata/generic-vdpa.x86_64-latest.args
new file mode 100644
index 0000000..7e904e2
--- /dev/null
+++ b/tests/qemuxmlconfdata/generic-vdpa.x86_64-latest.args
@@ -0,0 +1,34 @@
+LC_ALL=C \
+PATH=/bin \
+HOME=/var/lib/libvirt/qemu/domain--1-vm \
+USER=test \
+LOGNAME=test \
+XDG_DATA_HOME=/var/lib/libvirt/qemu/domain--1-vm/.local/share \
+XDG_CACHE_HOME=/var/lib/libvirt/qemu/domain--1-vm/.cache \
+XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-vm/.config \
+/usr/bin/qemu-system-x86_64 \
+-name guest=vm,debug-threads=on \
+-S \
+-object '{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/var/lib/libvirt/qemu/domain--1-vm/master-key.aes"}' \
+-machine pc-i440fx-8.0,usb=off,dump-guest-core=off,memory-backend=pc.ram,acpi=off \
+-accel tcg \
+-cpu qemu64,hypervisor=on,lahf-lm=on \
+-m size=2097152k \
+-object '{"qom-type":"memory-backend-file","id":"pc.ram","mem-path":"/var/lib/libvirt/qemu/ram/-1-vm/pc.ram","share":true,"x-use-canonical-path-for-ramblock-id":false,"size":2147483648}' \
+-overcommit mem-lock=off \
+-smp 2,sockets=2,cores=1,threads=1 \
+-uuid 85e32425-da0d-11ee-96fa-8430ce01b683 \
+-display none \
+-no-user-config \
+-nodefaults \
+-chardev socket,id=charmonitor,fd=1729,server=on,wait=off \
+-mon chardev=charmonitor,id=monitor,mode=control \
+-rtc base=utc \
+-no-shutdown \
+-boot strict=on \
+-device '{"driver":"piix3-usb-uhci","id":"usb","bus":"pci.0","addr":"0x1.0x2"}' \
+-audiodev '{"id":"audio1","driver":"none"}' \
+-device '{"driver":"virtio-balloon-pci","id":"balloon0","bus":"pci.0","addr":"0x2"}' \
+-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \
+-device '{"driver":"vhost-vdpa-device-pci","vhostdev":"/dev/vhost-vdpa-0","id":"gvdpa0","bootindex":1,"bus":"pci.0","addr":"0x9"}' \
+-msg timestamp=on
diff --git a/tests/qemuxmlconfdata/generic-vdpa.x86_64-latest.xml b/tests/qemuxmlconfdata/generic-vdpa.x86_64-latest.xml
new file mode 120000
index 0000000..ce074fe
--- /dev/null
+++ b/tests/qemuxmlconfdata/generic-vdpa.x86_64-latest.xml
@@ -0,0 +1 @@
+generic-vdpa.xml
\ No newline at end of file
diff --git a/tests/qemuxmlconfdata/generic-vdpa.xml b/tests/qemuxmlconfdata/generic-vdpa.xml
new file mode 100644
index 0000000..f2c6bae
--- /dev/null
+++ b/tests/qemuxmlconfdata/generic-vdpa.xml
@@ -0,0 +1,43 @@
+<domain type='qemu'>
+  <name>vm</name>
+  <uuid>85e32425-da0d-11ee-96fa-8430ce01b683</uuid>
+  <memory unit='KiB'>2097152</memory>
+  <currentMemory unit='KiB'>2097152</currentMemory>
+  <memoryBacking>
+    <access mode='shared'/>
+  </memoryBacking>
+  <vcpu placement='static'>2</vcpu>
+  <resource>
+    <partition>/machine</partition>
+  </resource>
+  <os>
+    <type arch='x86_64' machine='pc-i440fx-8.0'>hvm</type>
+  </os>
+  <cpu mode='custom' match='exact' check='full'>
+    <model fallback='forbid'>qemu64</model>
+    <feature policy='require' name='hypervisor'/>
+    <feature policy='require' name='lahf_lm'/>
+  </cpu>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <devices>
+    <emulator>/usr/bin/qemu-system-x86_64</emulator>
+    <controller type='usb' index='0' model='piix3-uhci'>
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/>
+    </controller>
+    <controller type='pci' index='0' model='pci-root'/>
+    <input type='mouse' bus='ps2'/>
+    <input type='keyboard' bus='ps2'/>
+    <audio id='1' type='none'/>
+    <memballoon model='virtio'>
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
+    </memballoon>
+    <gvdpa>
+      <source dev='/dev/vhost-vdpa-0'/>
+      <boot order='1'/>
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x09' function='0x0'/>
+    </gvdpa>
+  </devices>
+</domain>
diff --git a/tests/qemuxmlconftest.c b/tests/qemuxmlconftest.c
index 71b5913..357ab60 100644
--- a/tests/qemuxmlconftest.c
+++ b/tests/qemuxmlconftest.c
@@ -2910,6 +2910,7 @@ mymain(void)
     DO_TEST_CAPS_VER("sgx-epc", "7.0.0");
 
     DO_TEST_CAPS_LATEST("crypto-builtin");
+    DO_TEST_CAPS_LATEST("generic-vdpa");
 
     DO_TEST_CAPS_LATEST("async-teardown");
     DO_TEST_CAPS_ARCH_LATEST("s390-async-teardown", "s390x");
-- 
2.25.1
_______________________________________________
Devel mailing list -- devel@xxxxxxxxxxxxxxxxx
To unsubscribe send an email to devel-leave@xxxxxxxxxxxxxxxxx




[Index of Archives]     [Virt Tools]     [Libvirt Users]     [Lib OS Info]     [Fedora Users]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [KDE Users]     [Fedora Tools]

  Powered by Linux