From ccb6ee3cd899a2209cbe29f6c3b70522b86323ba Mon Sep 17 00:00:00 2001
From: AlexChen <alex.chen@huawei.com>
Date: Sat, 25 Nov 2023 10:34:05 +0800
Subject: [PATCH] vdpa: Introduce the new device type vdpa to hostdev

Introduce the new device type vdpa to hostdev

Signed-off-by: libai <libai12@huawei.com>
Signed-off-by: jiangdongxu <jiangdongxu1@huawei.com>
Signed-off-by: AlexChen <alex.chen@huawei.com>
---
 src/conf/domain_audit.c         |  4 ++++
 src/conf/domain_conf.c          | 38 +++++++++++++++++++++++++++++++++
 src/conf/domain_conf.h          |  6 ++++++
 src/conf/virconftypes.h         |  3 +++
 src/qemu/qemu_command.c         | 29 +++++++++++++++++++++++++
 src/qemu/qemu_command.h         |  4 ++++
 src/qemu/qemu_domain.c          |  7 ++++++
 src/qemu/qemu_domain_address.c  |  6 ++++--
 src/security/security_dac.c     |  2 ++
 src/security/security_selinux.c |  2 ++
 10 files changed, 99 insertions(+), 2 deletions(-)

diff --git a/src/conf/domain_audit.c b/src/conf/domain_audit.c
index 1b0abb21a0..d920dcbf09 100644
--- a/src/conf/domain_audit.c
+++ b/src/conf/domain_audit.c
@@ -350,6 +350,7 @@ virDomainAuditHostdev(virDomainObjPtr vm, virDomainHostdevDefPtr hostdev,
     virDomainHostdevSubsysSCSIPtr scsisrc = &hostdev->source.subsys.u.scsi;
     virDomainHostdevSubsysSCSIVHostPtr hostsrc = &hostdev->source.subsys.u.scsi_host;
     virDomainHostdevSubsysMediatedDevPtr mdevsrc = &hostdev->source.subsys.u.mdev;
+    virDomainHostdevSubsysVDPAPtr vdpasrc = &hostdev->source.subsys.u.vdpa;
 
     virUUIDFormat(vm->def->uuid, uuidstr);
     if (!(vmname = virAuditEncode("vm", vm->def->name))) {
@@ -393,6 +394,9 @@ virDomainAuditHostdev(virDomainObjPtr vm, virDomainHostdevDefPtr 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 7ae403424d..5a04d1b5d1 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -911,6 +911,7 @@ VIR_ENUM_IMPL(virDomainHostdevSubsys,
               "scsi",
               "scsi_host",
               "mdev",
+              "vdpa",
 );
 
 VIR_ENUM_IMPL(virDomainHostdevSubsysPCIBackend,
@@ -2980,6 +2981,9 @@ void virDomainHostdevDefClear(virDomainHostdevDefPtr def)
         case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST:
             VIR_FREE(def->source.subsys.u.scsi_host.wwpn);
             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_PCI:
         case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_MDEV:
@@ -6706,6 +6710,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;
         }
@@ -8590,6 +8595,22 @@ virDomainHostdevSubsysMediatedDevDefParseXML(virDomainHostdevDefPtr def,
     return 0;
 }
 
+static int
+virDomainHostdevSubsysVDPADefParseXML(virDomainHostdevDefPtr def,
+                                      xmlNodePtr sourcenode)
+{
+    g_autofree char *devpath = NULL;
+    virDomainHostdevSubsysVDPAPtr 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,
@@ -8779,6 +8800,11 @@ virDomainHostdevDefParseXMLSubsys(xmlNodePtr node,
         if (virDomainHostdevSubsysMediatedDevDefParseXML(def, ctxt) < 0)
             return -1;
         break;
+    case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_VDPA:
+        if (virDomainHostdevSubsysVDPADefParseXML(def, sourcenode) < 0) {
+            return -1;
+        }
+        break;
 
     default:
         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
@@ -16328,6 +16354,7 @@ virDomainHostdevDefParseXML(virDomainXMLOptionPtr 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;
         }
@@ -17407,6 +17434,9 @@ virDomainHostdevMatchSubsys(virDomainHostdevDefPtr a,
             return 0;
     case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_MDEV:
         return virDomainHostdevMatchSubsysMediatedDev(a, b);
+    case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_VDPA:
+        return STREQ(a->source.subsys.u.vdpa.devpath,
+                     b->source.subsys.u.vdpa.devpath);
     case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST:
         return 0;
     }
@@ -25891,6 +25921,7 @@ virDomainHostdevDefFormatSubsys(virBufferPtr buf,
     virDomainHostdevSubsysSCSIPtr scsisrc = &def->source.subsys.u.scsi;
     virDomainHostdevSubsysSCSIVHostPtr hostsrc = &def->source.subsys.u.scsi_host;
     virDomainHostdevSubsysMediatedDevPtr mdevsrc = &def->source.subsys.u.mdev;
+    virDomainHostdevSubsysVDPAPtr vdpasrc = &def->source.subsys.u.vdpa;
     virDomainHostdevSubsysSCSIHostPtr scsihostsrc = &scsisrc->u.host;
     virDomainHostdevSubsysSCSIiSCSIPtr iscsisrc = &scsisrc->u.iscsi;
 
@@ -25940,6 +25971,11 @@ virDomainHostdevDefFormatSubsys(virBufferPtr buf,
                           protocol, hostsrc->wwpn);
     }
 
+    if (def->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_VDPA) {
+        closedSource = true;
+        virBufferAsprintf(buf, " dev='%s'/", vdpasrc->devpath);
+    }
+
     virBufferAddLit(buf, ">\n");
 
     virBufferAdjustIndent(buf, 2);
@@ -25998,6 +26034,8 @@ virDomainHostdevDefFormatSubsys(virBufferPtr buf,
         virBufferAsprintf(buf, "<address uuid='%s'/>\n",
                           mdevsrc->uuidstr);
         break;
+    case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_VDPA:
+        break;
     default:
         virReportError(VIR_ERR_INTERNAL_ERROR,
                        _("unexpected hostdev type %d"),
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 98fa323679..6d56ef0282 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -199,6 +199,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;
@@ -267,6 +268,10 @@ struct _virDomainHostdevSubsysMediatedDev {
     int ramfb; /* virTristateSwitch */
 };
 
+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,
@@ -301,6 +306,7 @@ struct _virDomainHostdevSubsys {
         virDomainHostdevSubsysSCSI scsi;
         virDomainHostdevSubsysSCSIVHost scsi_host;
         virDomainHostdevSubsysMediatedDev mdev;
+        virDomainHostdevSubsysVDPA vdpa;
     } u;
 };
 
diff --git a/src/conf/virconftypes.h b/src/conf/virconftypes.h
index 1c62cde251..ca1a17b262 100644
--- a/src/conf/virconftypes.h
+++ b/src/conf/virconftypes.h
@@ -174,6 +174,9 @@ typedef virDomainHostdevSubsys *virDomainHostdevSubsysPtr;
 typedef struct _virDomainHostdevSubsysMediatedDev virDomainHostdevSubsysMediatedDev;
 typedef virDomainHostdevSubsysMediatedDev *virDomainHostdevSubsysMediatedDevPtr;
 
+typedef struct _virDomainHostdevSubsysVDPA virDomainHostdevSubsysVDPA;
+typedef virDomainHostdevSubsysVDPA *virDomainHostdevSubsysVDPAPtr;
+
 typedef struct _virDomainHostdevSubsysPCI virDomainHostdevSubsysPCI;
 typedef virDomainHostdevSubsysPCI *virDomainHostdevSubsysPCIPtr;
 
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 832c17b602..d7db30d19b 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -5476,6 +5476,25 @@ qemuBuildHostdevMediatedDevStr(const virDomainDef *def,
     return virBufferContentAndReset(&buf);
 }
 
+char *
+qemuBuildHostdevVDPAStr(const virDomainDef *def,
+                        virDomainHostdevDefPtr dev,
+                        virQEMUCapsPtr qemuCaps)
+{
+    g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
+    virDomainHostdevSubsysVDPAPtr vdpa = &dev->source.subsys.u.vdpa;
+    if (!vdpa->devpath) {
+        return NULL;
+    }
+
+    virBufferAdd(&buf, "vhost-vdpa-device-pci", -1);
+    virBufferAsprintf(&buf, ",id=%s", dev->info->alias);
+    virBufferAsprintf(&buf, ",vhostdev=%s", vdpa->devpath);
+    if (qemuBuildDeviceAddressStr(&buf, def, dev->info, qemuCaps) < 0)
+        return NULL;
+    return virBufferContentAndReset(&buf);
+}
+
 static int
 qemuBuildHostdevCommandLine(virCommandPtr cmd,
                             const virDomainDef *def,
@@ -5607,6 +5626,16 @@ qemuBuildHostdevCommandLine(virCommandPtr cmd,
 
             break;
 
+        /* VDPA */
+        case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_VDPA:
+            virCommandAddArg(cmd, "-device");
+            if (!(devstr = qemuBuildHostdevVDPAStr(def, hostdev, qemuCaps))) {
+                return -1;
+            }
+            virCommandAddArg(cmd, devstr);
+
+            break;
+
         case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST:
             break;
         }
diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h
index 283aaf358c..080cf41b81 100644
--- a/src/qemu/qemu_command.h
+++ b/src/qemu/qemu_command.h
@@ -198,6 +198,10 @@ char *
 qemuBuildHostdevMediatedDevStr(const virDomainDef *def,
                                virDomainHostdevDefPtr dev,
                                virQEMUCapsPtr qemuCaps);
+char *
+qemuBuildHostdevVDPAStr(const virDomainDef *def,
+                        virDomainHostdevDefPtr dev,
+                        virQEMUCapsPtr qemuCaps);
 
 char *qemuBuildRedirdevDevStr(const virDomainDef *def,
                               virDomainRedirdevDefPtr dev,
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 5933039f5c..fd3e3f64c0 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -6879,6 +6879,8 @@ qemuDomainDeviceDefValidateHostdev(const virDomainHostdevDef *hostdev,
             break;
         case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_MDEV:
             return qemuDomainMdevDefValidate(hostdev, def, qemuCaps);
+        case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_VDPA:
+            break;
         case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST:
         default:
             virReportEnumRangeError(virDomainHostdevSubsysType,
@@ -14442,6 +14444,7 @@ qemuDomainGetHostdevPath(virDomainHostdevDefPtr dev,
     virDomainHostdevSubsysSCSIPtr scsisrc = &dev->source.subsys.u.scsi;
     virDomainHostdevSubsysSCSIVHostPtr hostsrc = &dev->source.subsys.u.scsi_host;
     virDomainHostdevSubsysMediatedDevPtr mdevsrc = &dev->source.subsys.u.mdev;
+    virDomainHostdevSubsysVDPAPtr vdpasrc = &dev->source.subsys.u.vdpa;
     g_autoptr(virUSBDevice) usb = NULL;
     g_autoptr(virSCSIDevice) scsi = NULL;
     g_autoptr(virSCSIVHostDevice) host = NULL;
@@ -14512,6 +14515,10 @@ qemuDomainGetHostdevPath(virDomainHostdevDefPtr 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_domain_address.c b/src/qemu/qemu_domain_address.c
index 7f48773832..6649553486 100644
--- a/src/qemu/qemu_domain_address.c
+++ b/src/qemu/qemu_domain_address.c
@@ -792,7 +792,8 @@ qemuDomainDeviceCalculatePCIConnectFlags(virDomainDeviceDefPtr dev,
         if (!virHostdevIsMdevDevice(hostdev) &&
             (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS ||
              (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI &&
-              hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST))) {
+              hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST &&
+              hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_VDPA))) {
             return 0;
         }
 
@@ -2418,7 +2419,8 @@ qemuDomainAssignDevicePCISlots(virDomainDefPtr def,
         if (subsys->type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI &&
             subsys->type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST &&
             !(subsys->type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_MDEV &&
-              subsys->u.mdev.model == VIR_MDEV_MODEL_TYPE_VFIO_PCI)) {
+              subsys->u.mdev.model == VIR_MDEV_MODEL_TYPE_VFIO_PCI) &&
+            subsys->type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_VDPA) {
             continue;
         }
 
diff --git a/src/security/security_dac.c b/src/security/security_dac.c
index 51cabf1961..52b3c156e4 100644
--- a/src/security/security_dac.c
+++ b/src/security/security_dac.c
@@ -1357,6 +1357,7 @@ virSecurityDACSetHostdevLabel(virSecurityManagerPtr mgr,
         break;
     }
 
+    case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_VDPA:
     case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST:
         ret = 0;
         break;
@@ -1520,6 +1521,7 @@ virSecurityDACRestoreHostdevLabel(virSecurityManagerPtr 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 cb4dc3e101..54cb42fb8d 100644
--- a/src/security/security_selinux.c
+++ b/src/security/security_selinux.c
@@ -2213,6 +2213,7 @@ virSecuritySELinuxSetHostdevSubsysLabel(virSecurityManagerPtr mgr,
         break;
     }
 
+    case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_VDPA:
     case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST:
         ret = 0;
         break;
@@ -2449,6 +2450,7 @@ virSecuritySELinuxRestoreHostdevSubsysLabel(virSecurityManagerPtr mgr,
         break;
     }
 
+    case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_VDPA:
     case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST:
         ret = 0;
         break;
-- 
2.27.0

