diff mbox series

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

Message ID 1689731808-3009-2-git-send-email-yui.washidu@gmail.com (mailing list archive)
State New, archived
Headers show
Series virtio-net: add support for SR-IOV emulation | expand

Commit Message

Yui Washizu July 19, 2023, 1:56 a.m. UTC
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(-)

Comments

Akihiko Odaki July 20, 2023, 12:45 a.m. UTC | #1
On 2023/07/19 10:56, Yui Washizu wrote:
> 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");

Missing: return;

>       }
>   
>       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;
Jason Wang July 20, 2023, 2:19 a.m. UTC | #2
On Wed, Jul 19, 2023 at 9:59 AM Yui Washizu <yui.washidu@gmail.com> wrote:
>
> 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);

We probably don't need another memory bar for notification.

Thanks

> +            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
>
diff mbox series

Patch

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;