On Mon, Apr 24, 2023 at 11:55 AM libai <libai12@xxxxxxxxxx> wrote: > > The following is the xml of vdpa device: > <devices> > <hostdev mode='subsystem' type='vdpa'> > <source dev='/dev/vhost-vdpa-0'/> > </hostdev> > </devices> > And the command line passed to QEMU is as follows: > -device {"driver":"vhost-vdpa-device-pci","vhostdev":"/dev/vhost-vdpa-0"} > > This solution is selected according to the previous discussion > on the solution of supporting the vDPA device. > For details, see the following: > https://listman.redhat.com/archives/libvir-list/2023-March/239018.html It would be also helpful if you can point to some links to explain the generic vDPA device. Adding Laine and Jonathon for comments. Thanks > > Signed-off-by: libai <libai12@xxxxxxxxxx> > --- > src/conf/domain_audit.c | 4 +++ > src/conf/domain_conf.c | 47 +++++++++++++++++++++++++++++++++ > src/conf/domain_conf.h | 6 +++++ > src/conf/domain_validate.c | 1 + > src/conf/virconftypes.h | 2 ++ > src/qemu/qemu_command.c | 19 +++++++++++++ > src/qemu/qemu_command.h | 3 +++ > src/qemu/qemu_domain.c | 6 +++++ > src/qemu/qemu_hotplug.c | 1 + > src/qemu/qemu_migration.c | 2 ++ > src/qemu/qemu_validate.c | 2 ++ > src/security/security_dac.c | 2 ++ > src/security/security_selinux.c | 2 ++ > 13 files changed, 97 insertions(+) > > diff --git a/src/conf/domain_audit.c b/src/conf/domain_audit.c > index ae875188bd..6906ce7ade 100644 > --- a/src/conf/domain_audit.c > +++ b/src/conf/domain_audit.c > @@ -344,6 +344,7 @@ virDomainAuditHostdev(virDomainObj *vm, virDomainHostdevDef *hostdev, > virDomainHostdevSubsysSCSI *scsisrc = &hostdev->source.subsys.u.scsi; > virDomainHostdevSubsysSCSIVHost *hostsrc = &hostdev->source.subsys.u.scsi_host; > virDomainHostdevSubsysMediatedDev *mdevsrc = &hostdev->source.subsys.u.mdev; > + virDomainHostdevSubsysVDPA *vdpasrc = &hostdev->source.subsys.u.vdpa; > > virUUIDFormat(vm->def->uuid, uuidstr); > if (!(vmname = virAuditEncode("vm", vm->def->name))) { > @@ -383,6 +384,9 @@ virDomainAuditHostdev(virDomainObj *vm, virDomainHostdevDef *hostdev, > case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_MDEV: > address = g_strdup(mdevsrc->uuidstr); > break; > + case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_VDPA: > + address = g_strdup(vdpasrc->devpath); > + break; > case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST: > default: > VIR_WARN("Unexpected hostdev type while encoding audit message: %d", > diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c > index b03a3ff011..e8f6d1457b 100644 > --- a/src/conf/domain_conf.c > +++ b/src/conf/domain_conf.c > @@ -1047,6 +1047,7 @@ VIR_ENUM_IMPL(virDomainHostdevSubsys, > "scsi", > "scsi_host", > "mdev", > + "vdpa", > ); > > VIR_ENUM_IMPL(virDomainHostdevSubsysPCIBackend, > @@ -2641,6 +2642,9 @@ virDomainHostdevDefClear(virDomainHostdevDef *def) > case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI: > g_clear_pointer(&def->source.subsys.u.pci.origstates, virBitmapFree); > break; > + case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_VDPA: > + VIR_FREE(def->source.subsys.u.vdpa.devpath); > + break; > case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB: > case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_MDEV: > case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST: > @@ -6160,6 +6164,22 @@ virDomainHostdevSubsysMediatedDevDefParseXML(virDomainHostdevDef *def, > return 0; > } > > +static int > +virDomainHostdevSubsysVDPADefParseXML(xmlNodePtr sourcenode, > + virDomainHostdevDef *def) > +{ > + g_autofree char *devpath = NULL; > + virDomainHostdevSubsysVDPA *vdpa = &def->source.subsys.u.vdpa; > + > + if(!(devpath = virXMLPropString(sourcenode, "dev"))) { > + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", > + _("Missing 'dev' attribute for element <source>")); > + return -1; > + } > + vdpa->devpath = g_steal_pointer(&devpath); > + return 0; > +} > + > static int > virDomainHostdevDefParseXMLSubsys(xmlNodePtr node, > xmlXPathContextPtr ctxt, > @@ -6317,6 +6337,11 @@ virDomainHostdevDefParseXMLSubsys(xmlNodePtr node, > if (virDomainHostdevSubsysMediatedDevDefParseXML(def, ctxt) < 0) > return -1; > break; > + case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_VDPA: > + if (virDomainHostdevSubsysVDPADefParseXML(sourcenode, def) < 0) { > + return -1; > + } > + break; > > default: > virReportError(VIR_ERR_CONFIG_UNSUPPORTED, > @@ -12979,6 +13004,7 @@ virDomainHostdevDefParseXML(virDomainXMLOption *xmlopt, > case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI: > case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST: > case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_MDEV: > + case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_VDPA: > case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST: > break; > } > @@ -14101,6 +14127,13 @@ virDomainHostdevMatchSubsys(virDomainHostdevDef *a, > return 0; > case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_MDEV: > return virDomainHostdevMatchSubsysMediatedDev(a, b); > + case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_VDPA: > + if (STREQ(a->source.subsys.u.vdpa.devpath, > + b->source.subsys.u.vdpa.devpath)) { > + return 1; > + } else { > + return 0; > + } > case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST: > return 0; > } > @@ -23290,6 +23323,16 @@ virDomainHostdevDefFormatSubsysMdev(virBuffer *buf, > virXMLFormatElement(buf, "source", NULL, &sourceChildBuf); > } > > +static void > +virDomainHostdevDefFormatSubsysVDPA(virBuffer *buf, > + virDomainHostdevDef *def) > +{ > + g_auto(virBuffer) sourceAttrBuf = VIR_BUFFER_INITIALIZER; > + virDomainHostdevSubsysVDPA *vdpasrc = &def->source.subsys.u.vdpa; > + virBufferAsprintf(&sourceAttrBuf, " dev='%s'", vdpasrc->devpath); > + virXMLFormatElement(buf, "source", &sourceAttrBuf, NULL); > +} > + > > static int > virDomainHostdevDefFormatSubsys(virBuffer *buf, > @@ -23317,6 +23360,10 @@ virDomainHostdevDefFormatSubsys(virBuffer *buf, > virDomainHostdevDefFormatSubsysMdev(buf, def); > return 0; > > + case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_VDPA: > + virDomainHostdevDefFormatSubsysVDPA(buf, def); > + return 0; > + > case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST: > default: > virReportEnumRangeError(virDomainHostdevSubsysType, def->source.subsys.type); > diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h > index 511067a050..ade8b0edec 100644 > --- a/src/conf/domain_conf.h > +++ b/src/conf/domain_conf.h > @@ -197,6 +197,7 @@ typedef enum { > VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI, > VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST, > VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_MDEV, > + VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_VDPA, > > VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST > } virDomainHostdevSubsysType; > @@ -289,6 +290,10 @@ struct _virDomainHostdevSubsysMediatedDev { > virTristateSwitch ramfb; > }; > > +struct _virDomainHostdevSubsysVDPA { > + char *devpath; /* vDPA device path */ > +}; > + > typedef enum { > VIR_DOMAIN_HOSTDEV_SUBSYS_SCSI_HOST_PROTOCOL_TYPE_NONE, > VIR_DOMAIN_HOSTDEV_SUBSYS_SCSI_HOST_PROTOCOL_TYPE_VHOST, > @@ -323,6 +328,7 @@ struct _virDomainHostdevSubsys { > virDomainHostdevSubsysSCSI scsi; > virDomainHostdevSubsysSCSIVHost scsi_host; > virDomainHostdevSubsysMediatedDev mdev; > + virDomainHostdevSubsysVDPA vdpa; > } u; > }; > > diff --git a/src/conf/domain_validate.c b/src/conf/domain_validate.c > index e04b85fee4..4af84c4f0c 100644 > --- a/src/conf/domain_validate.c > +++ b/src/conf/domain_validate.c > @@ -2214,6 +2214,7 @@ virDomainHostdevDefValidate(const virDomainHostdevDef *hostdev) > } > break; > case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_MDEV: > + case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_VDPA: > case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST: > break; > } > diff --git a/src/conf/virconftypes.h b/src/conf/virconftypes.h > index e07f967814..1756c54e7a 100644 > --- a/src/conf/virconftypes.h > +++ b/src/conf/virconftypes.h > @@ -120,6 +120,8 @@ typedef struct _virDomainHostdevSubsys virDomainHostdevSubsys; > > typedef struct _virDomainHostdevSubsysMediatedDev virDomainHostdevSubsysMediatedDev; > > +typedef struct _virDomainHostdevSubsysVDPA virDomainHostdevSubsysVDPA; > + > typedef struct _virDomainHostdevSubsysPCI virDomainHostdevSubsysPCI; > > typedef struct _virDomainHostdevSubsysSCSI virDomainHostdevSubsysSCSI; > diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c > index 4ca93bf3dc..121214f4d5 100644 > --- a/src/qemu/qemu_command.c > +++ b/src/qemu/qemu_command.c > @@ -4958,6 +4958,18 @@ qemuBuildHostdevMediatedDevProps(const virDomainDef *def, > return g_steal_pointer(&props); > } > > +virJSONValue * > +qemuBuildHostdevVDPADevProps(virDomainHostdevDef *dev) > +{ > + g_autoptr(virJSONValue) props = NULL; > + virDomainHostdevSubsysVDPA *vdpasrc = &dev->source.subsys.u.vdpa; > + if (virJSONValueObjectAdd(&props, > + "s:driver", "vhost-vdpa-device-pci", > + "s:vhostdev", vdpasrc->devpath, > + NULL) < 0) > + return NULL; > + return g_steal_pointer(&props); > +} > > qemuBlockStorageSourceAttachData * > qemuBuildHostdevSCSIDetachPrepare(virDomainHostdevDef *hostdev, > @@ -5154,6 +5166,13 @@ qemuBuildHostdevCommandLine(virCommand *cmd, > return -1; > break; > > + case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_VDPA: > + if (!(devprops = qemuBuildHostdevVDPADevProps(hostdev))) > + return -1; > + if (qemuBuildDeviceCommandlineFromJSON(cmd, devprops, def, qemuCaps) < 0) > + return -1; > + break; > + > case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST: > break; > } > diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h > index 5fdb138030..dff18350b5 100644 > --- a/src/qemu/qemu_command.h > +++ b/src/qemu/qemu_command.h > @@ -198,6 +198,9 @@ virJSONValue * > qemuBuildHostdevMediatedDevProps(const virDomainDef *def, > virDomainHostdevDef *dev); > > +virJSONValue * > +qemuBuildHostdevVDPADevProps(virDomainHostdevDef *dev); > + > virJSONValue * > qemuBuildRedirdevDevProps(const virDomainDef *def, > virDomainRedirdevDef *dev); > diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c > index 63b13b6875..0cd485a459 100644 > --- a/src/qemu/qemu_domain.c > +++ b/src/qemu/qemu_domain.c > @@ -10533,6 +10533,8 @@ qemuDomainGetHostdevPath(virDomainHostdevDef *dev, > virDomainHostdevSubsysSCSI *scsisrc = &dev->source.subsys.u.scsi; > virDomainHostdevSubsysSCSIVHost *hostsrc = &dev->source.subsys.u.scsi_host; > virDomainHostdevSubsysMediatedDev *mdevsrc = &dev->source.subsys.u.mdev; > + virDomainHostdevSubsysVDPA *vdpasrc = &dev->source.subsys.u.vdpa; > + > g_autoptr(virUSBDevice) usb = NULL; > g_autoptr(virSCSIDevice) scsi = NULL; > g_autoptr(virSCSIVHostDevice) host = NULL; > @@ -10603,6 +10605,10 @@ qemuDomainGetHostdevPath(virDomainHostdevDef *dev, > if (!(tmpPath = virMediatedDeviceGetIOMMUGroupDev(mdevsrc->uuidstr))) > return -1; > > + perm = VIR_CGROUP_DEVICE_RW; > + break; > + case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_VDPA: > + tmpPath = g_strdup(vdpasrc->devpath); > perm = VIR_CGROUP_DEVICE_RW; > break; > case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST: > diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c > index 5072798cb7..7d89899223 100644 > --- a/src/qemu/qemu_hotplug.c > +++ b/src/qemu/qemu_hotplug.c > @@ -4546,6 +4546,7 @@ qemuDomainRemoveHostDevice(virQEMUDriver *driver, > case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_MDEV: > qemuDomainRemoveMediatedDevice(driver, vm, hostdev); > break; > + case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_VDPA: > case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST: > break; > } > diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c > index ed41a03851..9220ef1ab1 100644 > --- a/src/qemu/qemu_migration.c > +++ b/src/qemu/qemu_migration.c > @@ -1295,6 +1295,8 @@ qemuMigrationSrcIsAllowedHostdev(const virDomainDef *def) > case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI: > case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST: > case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_MDEV: > + /* The vDPA devices don't support migration for now */ > + case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_VDPA: > virReportError(VIR_ERR_OPERATION_UNSUPPORTED, > _("cannot migrate a domain with <hostdev mode='subsystem' type='%1$s'>"), > virDomainHostdevSubsysTypeToString(hostdev->source.subsys.type)); > diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c > index b8d5e9bd74..ea3d4e1a39 100644 > --- a/src/qemu/qemu_validate.c > +++ b/src/qemu/qemu_validate.c > @@ -2566,6 +2566,8 @@ qemuValidateDomainDeviceDefHostdev(const virDomainHostdevDef *hostdev, > break; > case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_MDEV: > return qemuValidateDomainMdevDef(hostdev, def, qemuCaps); > + case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_VDPA: > + break; > case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST: > default: > virReportEnumRangeError(virDomainHostdevSubsysType, > diff --git a/src/security/security_dac.c b/src/security/security_dac.c > index c7dc145621..24f3de5d15 100644 > --- a/src/security/security_dac.c > +++ b/src/security/security_dac.c > @@ -1313,6 +1313,7 @@ virSecurityDACSetHostdevLabel(virSecurityManager *mgr, > break; > } > > + case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_VDPA: > case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST: > ret = 0; > break; > @@ -1469,6 +1470,7 @@ virSecurityDACRestoreHostdevLabel(virSecurityManager *mgr, > break; > } > > + case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_VDPA: > case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST: > ret = 0; > break; > diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c > index e3e6a6115f..5cb6612fbc 100644 > --- a/src/security/security_selinux.c > +++ b/src/security/security_selinux.c > @@ -2265,6 +2265,7 @@ virSecuritySELinuxSetHostdevSubsysLabel(virSecurityManager *mgr, > break; > } > > + case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_VDPA: > case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST: > ret = 0; > break; > @@ -2493,6 +2494,7 @@ virSecuritySELinuxRestoreHostdevSubsysLabel(virSecurityManager *mgr, > break; > } > > + case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_VDPA: > case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST: > ret = 0; > break; > -- > 2.33.0 >