diff options
author | Michael S. Tsirkin <mst@redhat.com> | 2024-08-01 03:44:19 -0400 |
---|---|---|
committer | Michael S. Tsirkin <mst@redhat.com> | 2024-08-01 04:32:00 -0400 |
commit | aa01c4914ed6f6c087ee172483e22a515c4cc66a (patch) | |
tree | 87869456cd882a56b988503f4eb7ed4b7106379d /hw/pci/pcie_sriov.c | |
parent | 67f5b279fc72e43ccdee20a1a1e54cb51e24f06a (diff) | |
download | qemu-aa01c4914ed6f6c087ee172483e22a515c4cc66a.zip qemu-aa01c4914ed6f6c087ee172483e22a515c4cc66a.tar.gz qemu-aa01c4914ed6f6c087ee172483e22a515c4cc66a.tar.bz2 |
Revert "pcie_sriov: Allow user to create SR-IOV device"
This reverts commit 122173a5830f7757f8a94a3b1559582f312e140b.
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Diffstat (limited to 'hw/pci/pcie_sriov.c')
-rw-r--r-- | hw/pci/pcie_sriov.c | 290 |
1 files changed, 58 insertions, 232 deletions
diff --git a/hw/pci/pcie_sriov.c b/hw/pci/pcie_sriov.c index 0fc9f81..15a4aac 100644 --- a/hw/pci/pcie_sriov.c +++ b/hw/pci/pcie_sriov.c @@ -20,8 +20,6 @@ #include "qapi/error.h" #include "trace.h" -static GHashTable *pfs; - static void unparent_vfs(PCIDevice *dev, uint16_t total_vfs) { for (uint16_t i = 0; i < total_vfs; i++) { @@ -33,49 +31,14 @@ static void unparent_vfs(PCIDevice *dev, uint16_t total_vfs) dev->exp.sriov_pf.vf = NULL; } -static void clear_ctrl_vfe(PCIDevice *dev) -{ - uint8_t *ctrl = dev->config + dev->exp.sriov_cap + PCI_SRIOV_CTRL; - pci_set_word(ctrl, pci_get_word(ctrl) & ~PCI_SRIOV_CTRL_VFE); -} - -static void register_vfs(PCIDevice *dev) -{ - uint16_t num_vfs; - uint16_t i; - uint16_t sriov_cap = dev->exp.sriov_cap; - - assert(sriov_cap > 0); - num_vfs = pci_get_word(dev->config + sriov_cap + PCI_SRIOV_NUM_VF); - if (num_vfs > pci_get_word(dev->config + sriov_cap + PCI_SRIOV_TOTAL_VF)) { - clear_ctrl_vfe(dev); - return; - } - - trace_sriov_register_vfs(dev->name, PCI_SLOT(dev->devfn), - PCI_FUNC(dev->devfn), num_vfs); - for (i = 0; i < num_vfs; i++) { - pci_set_enabled(dev->exp.sriov_pf.vf[i], true); - } -} - -static void unregister_vfs(PCIDevice *dev) -{ - uint16_t i; - uint8_t *cfg = dev->config + dev->exp.sriov_cap; - - trace_sriov_unregister_vfs(dev->name, PCI_SLOT(dev->devfn), - PCI_FUNC(dev->devfn)); - for (i = 0; i < pci_get_word(cfg + PCI_SRIOV_TOTAL_VF); i++) { - pci_set_enabled(dev->exp.sriov_pf.vf[i], false); - } -} - -static bool pcie_sriov_pf_init_common(PCIDevice *dev, uint16_t offset, - uint16_t vf_dev_id, uint16_t init_vfs, - uint16_t total_vfs, uint16_t vf_offset, - uint16_t vf_stride, Error **errp) +bool pcie_sriov_pf_init(PCIDevice *dev, uint16_t offset, + const char *vfname, uint16_t vf_dev_id, + uint16_t init_vfs, uint16_t total_vfs, + uint16_t vf_offset, uint16_t vf_stride, + Error **errp) { + BusState *bus = qdev_get_parent_bus(&dev->qdev); + int32_t devfn = dev->devfn + vf_offset; uint8_t *cfg = dev->config + offset; uint8_t *wmask; @@ -137,28 +100,6 @@ static bool pcie_sriov_pf_init_common(PCIDevice *dev, uint16_t offset, qdev_prop_set_bit(&dev->qdev, "multifunction", true); - return true; -} - -bool pcie_sriov_pf_init(PCIDevice *dev, uint16_t offset, - const char *vfname, uint16_t vf_dev_id, - uint16_t init_vfs, uint16_t total_vfs, - uint16_t vf_offset, uint16_t vf_stride, - Error **errp) -{ - BusState *bus = qdev_get_parent_bus(&dev->qdev); - int32_t devfn = dev->devfn + vf_offset; - - if (pfs && g_hash_table_contains(pfs, dev->qdev.id)) { - error_setg(errp, "attaching user-created SR-IOV VF unsupported"); - return false; - } - - if (!pcie_sriov_pf_init_common(dev, offset, vf_dev_id, init_vfs, - total_vfs, vf_offset, vf_stride, errp)) { - return false; - } - dev->exp.sriov_pf.vf = g_new(PCIDevice *, total_vfs); for (uint16_t i = 0; i < total_vfs; i++) { @@ -188,24 +129,7 @@ void pcie_sriov_pf_exit(PCIDevice *dev) { uint8_t *cfg = dev->config + dev->exp.sriov_cap; - if (dev->exp.sriov_pf.vf_user_created) { - uint16_t ven_id = pci_get_word(dev->config + PCI_VENDOR_ID); - uint16_t total_vfs = pci_get_word(dev->config + PCI_SRIOV_TOTAL_VF); - uint16_t vf_dev_id = pci_get_word(dev->config + PCI_SRIOV_VF_DID); - - unregister_vfs(dev); - - for (uint16_t i = 0; i < total_vfs; i++) { - PCIDevice *vf = dev->exp.sriov_pf.vf[i]; - - vf->exp.sriov_vf.pf = NULL; - - pci_config_set_vendor_id(vf->config, ven_id); - pci_config_set_device_id(vf->config, vf_dev_id); - } - } else { - unparent_vfs(dev, pci_get_word(cfg + PCI_SRIOV_TOTAL_VF)); - } + unparent_vfs(dev, pci_get_word(cfg + PCI_SRIOV_TOTAL_VF)); } void pcie_sriov_pf_init_vf_bar(PCIDevice *dev, int region_num, @@ -238,172 +162,74 @@ void pcie_sriov_pf_init_vf_bar(PCIDevice *dev, int region_num, void pcie_sriov_vf_register_bar(PCIDevice *dev, int region_num, MemoryRegion *memory) { + PCIIORegion *r; + PCIBus *bus = pci_get_bus(dev); uint8_t type; + pcibus_t size = memory_region_size(memory); - assert(dev->exp.sriov_vf.pf); + assert(pci_is_vf(dev)); /* PFs must use pci_register_bar */ + assert(region_num >= 0); + assert(region_num < PCI_NUM_REGIONS); type = dev->exp.sriov_vf.pf->exp.sriov_pf.vf_bar_type[region_num]; - return pci_register_bar(dev, region_num, type, memory); + if (!is_power_of_2(size)) { + error_report("%s: PCI region size must be a power" + " of two - type=0x%x, size=0x%"FMT_PCIBUS, + __func__, type, size); + exit(1); + } + + r = &dev->io_regions[region_num]; + r->memory = memory; + r->address_space = + type & PCI_BASE_ADDRESS_SPACE_IO + ? bus->address_space_io + : bus->address_space_mem; + r->size = size; + r->type = type; + + r->addr = pci_bar_address(dev, region_num, r->type, r->size); + if (r->addr != PCI_BAR_UNMAPPED) { + memory_region_add_subregion_overlap(r->address_space, + r->addr, r->memory, 1); + } } -static gint compare_vf_devfns(gconstpointer a, gconstpointer b) +static void clear_ctrl_vfe(PCIDevice *dev) { - return (*(PCIDevice **)a)->devfn - (*(PCIDevice **)b)->devfn; + uint8_t *ctrl = dev->config + dev->exp.sriov_cap + PCI_SRIOV_CTRL; + pci_set_word(ctrl, pci_get_word(ctrl) & ~PCI_SRIOV_CTRL_VFE); } -int16_t pcie_sriov_pf_init_from_user_created_vfs(PCIDevice *dev, - uint16_t offset, - Error **errp) +static void register_vfs(PCIDevice *dev) { - GPtrArray *pf; - PCIDevice **vfs; - BusState *bus = qdev_get_parent_bus(DEVICE(dev)); - uint16_t ven_id = pci_get_word(dev->config + PCI_VENDOR_ID); - uint16_t vf_dev_id; - uint16_t vf_offset; - uint16_t vf_stride; + uint16_t num_vfs; uint16_t i; + uint16_t sriov_cap = dev->exp.sriov_cap; - if (!pfs || !dev->qdev.id) { - return 0; - } - - pf = g_hash_table_lookup(pfs, dev->qdev.id); - if (!pf) { - return 0; - } - - if (pf->len > UINT16_MAX) { - error_setg(errp, "too many VFs"); - return -1; - } - - g_ptr_array_sort(pf, compare_vf_devfns); - vfs = (void *)pf->pdata; - - if (vfs[0]->devfn <= dev->devfn) { - error_setg(errp, "a VF function number is less than the PF function number"); - return -1; - } - - vf_dev_id = pci_get_word(vfs[0]->config + PCI_DEVICE_ID); - vf_offset = vfs[0]->devfn - dev->devfn; - vf_stride = pf->len < 2 ? 0 : vfs[1]->devfn - vfs[0]->devfn; - - for (i = 0; i < pf->len; i++) { - if (bus != qdev_get_parent_bus(&vfs[i]->qdev)) { - error_setg(errp, "SR-IOV VF parent bus mismatches with PF"); - return -1; - } - - if (ven_id != pci_get_word(vfs[i]->config + PCI_VENDOR_ID)) { - error_setg(errp, "SR-IOV VF vendor ID mismatches with PF"); - return -1; - } - - if (vf_dev_id != pci_get_word(vfs[i]->config + PCI_DEVICE_ID)) { - error_setg(errp, "inconsistent SR-IOV VF device IDs"); - return -1; - } - - for (size_t j = 0; j < PCI_NUM_REGIONS; j++) { - if (vfs[i]->io_regions[j].size != vfs[0]->io_regions[j].size || - vfs[i]->io_regions[j].type != vfs[0]->io_regions[j].type) { - error_setg(errp, "inconsistent SR-IOV BARs"); - return -1; - } - } - - if (vfs[i]->devfn - vfs[0]->devfn != vf_stride * i) { - error_setg(errp, "inconsistent SR-IOV stride"); - return -1; - } - } - - if (!pcie_sriov_pf_init_common(dev, offset, vf_dev_id, pf->len, - pf->len, vf_offset, vf_stride, errp)) { - return -1; - } - - for (i = 0; i < pf->len; i++) { - vfs[i]->exp.sriov_vf.pf = dev; - vfs[i]->exp.sriov_vf.vf_number = i; - - /* set vid/did according to sr/iov spec - they are not used */ - pci_config_set_vendor_id(vfs[i]->config, 0xffff); - pci_config_set_device_id(vfs[i]->config, 0xffff); - } - - dev->exp.sriov_pf.vf = vfs; - dev->exp.sriov_pf.vf_user_created = true; - - for (i = 0; i < PCI_NUM_REGIONS; i++) { - PCIIORegion *region = &vfs[0]->io_regions[i]; - - if (region->size) { - pcie_sriov_pf_init_vf_bar(dev, i, region->type, region->size); - } - } - - return PCI_EXT_CAP_SRIOV_SIZEOF; -} - -bool pcie_sriov_register_device(PCIDevice *dev, Error **errp) -{ - if (!dev->exp.sriov_pf.vf && dev->qdev.id && - pfs && g_hash_table_contains(pfs, dev->qdev.id)) { - error_setg(errp, "attaching user-created SR-IOV VF unsupported"); - return false; + assert(sriov_cap > 0); + num_vfs = pci_get_word(dev->config + sriov_cap + PCI_SRIOV_NUM_VF); + if (num_vfs > pci_get_word(dev->config + sriov_cap + PCI_SRIOV_TOTAL_VF)) { + clear_ctrl_vfe(dev); + return; } - if (dev->sriov_pf) { - PCIDevice *pci_pf; - GPtrArray *pf; - - if (!PCI_DEVICE_GET_CLASS(dev)->sriov_vf_user_creatable) { - error_setg(errp, "user cannot create SR-IOV VF with this device type"); - return false; - } - - if (!pci_is_express(dev)) { - error_setg(errp, "PCI Express is required for SR-IOV VF"); - return false; - } - - if (!pci_qdev_find_device(dev->sriov_pf, &pci_pf)) { - error_setg(errp, "PCI device specified as SR-IOV PF already exists"); - return false; - } - - if (!pfs) { - pfs = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL); - } - - pf = g_hash_table_lookup(pfs, dev->sriov_pf); - if (!pf) { - pf = g_ptr_array_new(); - g_hash_table_insert(pfs, g_strdup(dev->sriov_pf), pf); - } - - g_ptr_array_add(pf, dev); + trace_sriov_register_vfs(dev->name, PCI_SLOT(dev->devfn), + PCI_FUNC(dev->devfn), num_vfs); + for (i = 0; i < num_vfs; i++) { + pci_set_enabled(dev->exp.sriov_pf.vf[i], true); } - - return true; } -void pcie_sriov_unregister_device(PCIDevice *dev) +static void unregister_vfs(PCIDevice *dev) { - if (dev->sriov_pf && pfs) { - GPtrArray *pf = g_hash_table_lookup(pfs, dev->sriov_pf); - - if (pf) { - g_ptr_array_remove_fast(pf, dev); + uint16_t i; + uint8_t *cfg = dev->config + dev->exp.sriov_cap; - if (!pf->len) { - g_hash_table_remove(pfs, dev->sriov_pf); - g_ptr_array_free(pf, FALSE); - } - } + trace_sriov_unregister_vfs(dev->name, PCI_SLOT(dev->devfn), + PCI_FUNC(dev->devfn)); + for (i = 0; i < pci_get_word(cfg + PCI_SRIOV_TOTAL_VF); i++) { + pci_set_enabled(dev->exp.sriov_pf.vf[i], false); } } @@ -490,7 +316,7 @@ void pcie_sriov_pf_add_sup_pgsize(PCIDevice *dev, uint16_t opt_sup_pgsize) uint16_t pcie_sriov_vf_number(PCIDevice *dev) { - assert(dev->exp.sriov_vf.pf); + assert(pci_is_vf(dev)); return dev->exp.sriov_vf.vf_number; } |