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(a)jaguarmicro.com>
---
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