diff --git a/hypervisor/dm/vpci/vdev.c b/hypervisor/dm/vpci/vdev.c index 705b93097..5b2b3afa2 100644 --- a/hypervisor/dm/vpci/vdev.c +++ b/hypervisor/dm/vpci/vdev.c @@ -31,6 +31,7 @@ #include "vpci_priv.h" #include #include +#include /** * @pre vdev != NULL @@ -78,14 +79,12 @@ void pci_vdev_write_vcfg(struct pci_vdev *vdev, uint32_t offset, uint32_t bytes, */ struct pci_vdev *pci_find_vdev(struct acrn_vpci *vpci, union pci_bdf vbdf) { - struct pci_vdev *vdev, *tmp; - uint32_t i; + struct pci_vdev *vdev = NULL, *tmp; + struct hlist_node *n; - vdev = NULL; - for (i = 0U; i < vpci->pci_vdev_cnt; i++) { - tmp = &(vpci->pci_vdevs[i]); - - if (bdf_is_equal(tmp->bdf, vbdf)) { + hlist_for_each(n, &vpci->vdevs_hlist_heads[hash64(vbdf.value, VDEV_LIST_HASHBITS)]) { + tmp = hlist_entry(n, struct pci_vdev, link); + if (bdf_is_equal(vbdf, tmp->bdf)) { vdev = tmp; break; } diff --git a/hypervisor/dm/vpci/vpci.c b/hypervisor/dm/vpci/vpci.c index bc5c4449a..c21a216b4 100644 --- a/hypervisor/dm/vpci/vpci.c +++ b/hypervisor/dm/vpci/vpci.c @@ -37,6 +37,7 @@ #include #include "vpci_priv.h" #include "pci_dev.h" +#include static void vpci_init_vdevs(struct acrn_vm *vm); static int32_t vpci_read_cfg(struct acrn_vpci *vpci, union pci_bdf bdf, uint32_t offset, uint32_t bytes, uint32_t *val); @@ -627,6 +628,7 @@ struct pci_vdev *vpci_init_vdev(struct acrn_vpci *vpci, struct acrn_vm_pci_dev_c vdev->pci_dev_config = dev_config; vdev->phyfun = parent_pf_vdev; + hlist_add_head(&vdev->link, &vpci->vdevs_hlist_heads[hash64(dev_config->vbdf.value, VDEV_LIST_HASHBITS)]); if (dev_config->vdev_ops != NULL) { vdev->vdev_ops = dev_config->vdev_ops; } else { @@ -726,6 +728,9 @@ int32_t vpci_assign_pcidev(struct acrn_vm *tgt_vm, struct acrn_assign_pcidev *pc vdev->flags |= pcidev->type; vdev->bdf.value = pcidev->virt_bdf; + /*We should re-add the vdev to hashlist since its vbdf has changed */ + hlist_del(&vdev->link); + hlist_add_head(&vdev->link, &vpci->vdevs_hlist_heads[hash64(vdev->bdf.value, VDEV_LIST_HASHBITS)]); vdev->parent_user = vdev_in_sos; spinlock_release(&tgt_vm->vpci.lock); vdev_in_sos->user = vdev; diff --git a/hypervisor/include/dm/vpci.h b/hypervisor/include/dm/vpci.h index e0e2f7170..57763ea53 100644 --- a/hypervisor/include/dm/vpci.h +++ b/hypervisor/include/dm/vpci.h @@ -32,7 +32,10 @@ #include #include +#include +#define VDEV_LIST_HASHBITS 4U +#define VDEV_LIST_HASHSIZE (1U << VDEV_LIST_HASHBITS) struct pci_vbar { enum pci_bar_type type; @@ -135,6 +138,7 @@ struct pci_vdev { */ struct pci_vdev *parent_user; struct pci_vdev *user; + struct hlist_node link; }; union pci_cfg_addr_reg { @@ -153,6 +157,7 @@ struct acrn_vpci { uint64_t pci_mmcfg_base; uint32_t pci_vdev_cnt; struct pci_vdev pci_vdevs[CONFIG_MAX_PCI_DEV_NUM]; + struct hlist_head vdevs_hlist_heads [VDEV_LIST_HASHSIZE]; }; struct acrn_vm;