qemu-devel
[Top][All Lists]
Advanced

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

[RFC 1/1] virtio-pci: add SR-IOV capability


From: Yui Washizu
Subject: [RFC 1/1] virtio-pci: add SR-IOV capability
Date: Wed, 19 Jul 2023 10:56:48 +0900

This enables SR-IOV emulation on virtio-pci devices by adding SR-IOV capability
It also introduces a newly added property 'sriov_max_vfs'
to enable or disable the SR-IOV feature on the virtio-pci device in guest,
as well as to specify the maximum number of VFs that can be created in the 
guest.
Currently only virtio-net is supported.
Also, the vendor ID and device ID remain the same for both the PF and VF,
enabling existing guest PF drivers to be used in the VF without any 
modifications.

Signed-off-by: Yui Washizu <yui.washidu@gmail.com>
---
 hw/pci/msix.c                  |  8 +++--
 hw/pci/pci.c                   |  4 +++
 hw/virtio/virtio-pci.c         | 62 ++++++++++++++++++++++++++++++----
 include/hw/virtio/virtio-pci.h |  1 +
 4 files changed, 66 insertions(+), 9 deletions(-)

diff --git a/hw/pci/msix.c b/hw/pci/msix.c
index ab8869d9d0..3b94ce389f 100644
--- a/hw/pci/msix.c
+++ b/hw/pci/msix.c
@@ -421,8 +421,12 @@ int msix_init_exclusive_bar(PCIDevice *dev, unsigned short 
nentries,
         return ret;
     }
 
-    pci_register_bar(dev, bar_nr, PCI_BASE_ADDRESS_SPACE_MEMORY,
-                     &dev->msix_exclusive_bar);
+    if (pci_is_vf(dev)) {
+        pcie_sriov_vf_register_bar(dev, bar_nr, &dev->msix_exclusive_bar);
+    } else {
+        pci_register_bar(dev, bar_nr, PCI_BASE_ADDRESS_SPACE_MEMORY,
+                         &dev->msix_exclusive_bar);
+    }
 
     return 0;
 }
diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index e2eb4c3b4a..cbd50b38ea 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -2325,6 +2325,10 @@ static void pci_add_option_rom(PCIDevice *pdev, bool 
is_default_rom,
         return;
     }
 
+    if (pci_is_vf(pdev)) {
+        return;
+    }
+
     if (!pdev->rom_bar) {
         /*
          * Load rom via fw_cfg instead of creating a rom bar,
diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
index edbc0daa18..2315c2647a 100644
--- a/hw/virtio/virtio-pci.c
+++ b/hw/virtio/virtio-pci.c
@@ -49,6 +49,8 @@
  * configuration space */
 #define VIRTIO_PCI_CONFIG_SIZE(dev)     
VIRTIO_PCI_CONFIG_OFF(msix_enabled(dev))
 
+#define VIRTIO_MAX_VFS 127
+
 static void virtio_pci_bus_new(VirtioBusState *bus, size_t bus_size,
                                VirtIOPCIProxy *dev);
 static void virtio_pci_reset(DeviceState *qdev);
@@ -1907,6 +1909,11 @@ static void virtio_pci_pre_plugged(DeviceState *d, Error 
**errp)
 
     if (virtio_pci_modern(proxy)) {
         virtio_add_feature(&vdev->host_features, VIRTIO_F_VERSION_1);
+        if (proxy->sriov_max_vfs) {
+            virtio_add_feature(&vdev->host_features, VIRTIO_F_SR_IOV);
+        }
+    } else if (proxy->sriov_max_vfs) {
+        error_setg(errp, "VirtIO PCI modern is required for the use of 
SR-IOV");
     }
 
     virtio_add_feature(&vdev->host_features, VIRTIO_F_BAD_FEATURE);
@@ -2015,22 +2022,62 @@ static void virtio_pci_device_plugged(DeviceState *d, 
Error **errp)
         virtio_pci_modern_mem_region_map(proxy, &proxy->device, &cap);
         virtio_pci_modern_mem_region_map(proxy, &proxy->notify, &notify.cap);
 
+        if (!pci_is_vf(&proxy->pci_dev) && proxy->sriov_max_vfs) {
+            if (virtio_bus_get_vdev_id(bus) != VIRTIO_ID_NET) {
+                error_setg(errp, "sriov_max_vfs prop is not supported by %s",
+                           proxy->pci_dev.name);
+                return;
+            }
+            if (proxy->sriov_max_vfs > VIRTIO_MAX_VFS) {
+                error_setg(errp, "sriov_max_vfs must be between 0 and %d",
+                           VIRTIO_MAX_VFS);
+                return;
+            }
+
+            pcie_sriov_pf_init(&proxy->pci_dev, PCI_CONFIG_SPACE_SIZE,
+                               proxy->pci_dev.name,
+                               PCI_DEVICE_ID_VIRTIO_10_BASE
+                               + virtio_bus_get_vdev_id(bus),
+                               proxy->sriov_max_vfs, proxy->sriov_max_vfs, 1, 
1);
+            if (proxy->flags & VIRTIO_PCI_FLAG_MODERN_PIO_NOTIFY) {
+                pcie_sriov_pf_init_vf_bar(&proxy->pci_dev, 
proxy->modern_io_bar_idx,
+                                          PCI_BASE_ADDRESS_SPACE_IO, 4);
+            }
+            if (proxy->nvectors) {
+                pcie_sriov_pf_init_vf_bar(&proxy->pci_dev, proxy->msix_bar_idx,
+                                          PCI_BASE_ADDRESS_SPACE_MEMORY, 4 * 
1024);
+            }
+            pcie_sriov_pf_init_vf_bar(&proxy->pci_dev, 
proxy->modern_mem_bar_idx,
+                                      PCI_BASE_ADDRESS_SPACE_MEMORY |
+                                      PCI_BASE_ADDRESS_MEM_PREFETCH |
+                                      PCI_BASE_ADDRESS_MEM_TYPE_64,
+                                      16 * 1024);
+        }
+
         if (modern_pio) {
             memory_region_init(&proxy->io_bar, OBJECT(proxy),
                                "virtio-pci-io", 0x4);
 
-            pci_register_bar(&proxy->pci_dev, proxy->modern_io_bar_idx,
-                             PCI_BASE_ADDRESS_SPACE_IO, &proxy->io_bar);
+            if (pci_is_vf(&proxy->pci_dev))
+                pcie_sriov_vf_register_bar(&proxy->pci_dev, 
proxy->modern_io_bar_idx,
+                                           &proxy->io_bar);
+            else
+                pci_register_bar(&proxy->pci_dev, proxy->modern_io_bar_idx,
+                                 PCI_BASE_ADDRESS_SPACE_IO, &proxy->io_bar);
 
             virtio_pci_modern_io_region_map(proxy, &proxy->notify_pio,
                                             &notify_pio.cap);
         }
 
-        pci_register_bar(&proxy->pci_dev, proxy->modern_mem_bar_idx,
-                         PCI_BASE_ADDRESS_SPACE_MEMORY |
-                         PCI_BASE_ADDRESS_MEM_PREFETCH |
-                         PCI_BASE_ADDRESS_MEM_TYPE_64,
-                         &proxy->modern_bar);
+        if (pci_is_vf(&proxy->pci_dev))
+            pcie_sriov_vf_register_bar(&proxy->pci_dev, 
proxy->modern_mem_bar_idx,
+                                       &proxy->modern_bar);
+        else
+            pci_register_bar(&proxy->pci_dev, proxy->modern_mem_bar_idx,
+                             PCI_BASE_ADDRESS_SPACE_MEMORY |
+                             PCI_BASE_ADDRESS_MEM_PREFETCH |
+                             PCI_BASE_ADDRESS_MEM_TYPE_64,
+                             &proxy->modern_bar);
 
         proxy->config_cap = virtio_pci_add_mem_cap(proxy, &cfg.cap);
         cfg_mask = (void *)(proxy->pci_dev.wmask + proxy->config_cap);
@@ -2298,6 +2345,7 @@ static Property virtio_pci_properties[] = {
                     VIRTIO_PCI_FLAG_INIT_FLR_BIT, true),
     DEFINE_PROP_BIT("aer", VirtIOPCIProxy, flags,
                     VIRTIO_PCI_FLAG_AER_BIT, false),
+    DEFINE_PROP_UINT16("sriov_max_vfs", VirtIOPCIProxy, sriov_max_vfs, 0),
     DEFINE_PROP_END_OF_LIST(),
 };
 
diff --git a/include/hw/virtio/virtio-pci.h b/include/hw/virtio/virtio-pci.h
index ab2051b64b..05ab6ddc3f 100644
--- a/include/hw/virtio/virtio-pci.h
+++ b/include/hw/virtio/virtio-pci.h
@@ -150,6 +150,7 @@ struct VirtIOPCIProxy {
     uint32_t flags;
     bool disable_modern;
     bool ignore_backend_features;
+    uint16_t sriov_max_vfs;
     OnOffAuto disable_legacy;
     /* Transitional device id */
     uint16_t trans_devid;
-- 
2.39.3




reply via email to

[Prev in Thread] Current Thread [Next in Thread]