On Wed, Jul 19, 2023 at 9:59 AM Yui Washizu <yui.wash...@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.wash...@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, ¬ify.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, > ¬ify_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 >