From 8fb8d81935fa9d8835f68d724475e1e6f0f33d5a Mon Sep 17 00:00:00 2001 From: Qian Wang Date: Fri, 5 Jun 2020 12:17:59 +0800 Subject: [PATCH] HV: refine pci_lookup_drhd_for_pbdf with hash hv: pci: refine pci_lookup_drhd_for_pbdf with hash 1. Added an auxiliary function pci_find_pdev using hash to find pdev with pbdf, thus pci_lookup_drhd_for_pbdf will have a better performance Tracked-On: #4857 Signed-off-by: Wang Qian Reviewed-by: Li Fei Acked-by: Eddie Dong --- hypervisor/hw/pci.c | 35 ++++++++++++++++++++++++----------- hypervisor/include/hw/pci.h | 3 +++ 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/hypervisor/hw/pci.c b/hypervisor/hw/pci.c index 6bcd002ec..8dbe40416 100644 --- a/hypervisor/hw/pci.c +++ b/hypervisor/hw/pci.c @@ -43,10 +43,16 @@ #include #include #include +#include +#include + +#define PDEV_HLIST_HASHBITS 6U +#define PDEV_HLIST_HASHSIZE (1U << PDEV_HLIST_HASHBITS) static spinlock_t pci_device_lock; static uint32_t num_pci_pdev; static struct pci_pdev pci_pdevs[CONFIG_MAX_PCI_DEV_NUM]; +static struct hlist_head pdevs_hlist_heads[PDEV_HLIST_HASHSIZE]; static uint64_t pci_mmcfg_base = DEFAULT_PCI_MMCFG_BASE; #ifdef CONFIG_ACPI_PARSE_ENABLED @@ -258,6 +264,21 @@ void pdev_restore_bar(const struct pci_pdev *pdev) } } +static const struct pci_pdev *pci_find_pdev(uint16_t pbdf) +{ + struct hlist_node *n; + const struct pci_pdev *found = NULL, *tmp; + + hlist_for_each (n, &pdevs_hlist_heads[hash64(pbdf, PDEV_HLIST_HASHBITS)]) { + tmp = hlist_entry(n, struct pci_pdev, link); + if (pbdf == tmp->bdf.value) { + found = tmp; + break; + } + } + return found; +} + /* @brief: Find the DRHD index corresponding to a PCI device * Runs through the pci_pdevs and returns the value in drhd_idx * member from pdev structure that matches matches B:D.F @@ -269,17 +290,8 @@ void pdev_restore_bar(const struct pci_pdev *pdev) uint32_t pci_lookup_drhd_for_pbdf(uint16_t pbdf) { - uint32_t drhd_index = INVALID_DRHD_INDEX; - uint32_t index; - - for (index = 0U; index < num_pci_pdev; index++) { - if (pci_pdevs[index].bdf.value == pbdf) { - drhd_index = pci_pdevs[index].drhd_index; - break; - } - } - - return drhd_index; + const struct pci_pdev *pdev = pci_find_pdev(pbdf); + return (pdev != NULL) ? pdev->drhd_index : INVALID_DRHD_INDEX; } /* enable: 1: enable INTx; 0: Disable INTx */ @@ -765,6 +777,7 @@ struct pci_pdev *init_pdev(uint16_t pbdf, uint32_t drhd_index) pci_enumerate_cap(pdev); } + hlist_add_head(&pdev->link, &pdevs_hlist_heads[hash64(pbdf, PDEV_HLIST_HASHBITS)]); pdev->drhd_index = drhd_index; num_pci_pdev++; reserve_vmsix_on_msi_irtes(pdev); diff --git a/hypervisor/include/hw/pci.h b/hypervisor/include/hw/pci.h index a48e6523e..2efc2d569 100644 --- a/hypervisor/include/hw/pci.h +++ b/hypervisor/include/hw/pci.h @@ -31,6 +31,8 @@ #ifndef PCI_H_ #define PCI_H_ +#include + /* * PCIM_xxx: mask to locate subfield in register * PCIR_xxx: config register offset @@ -248,6 +250,7 @@ struct pci_pdev { bool has_pm_reset; bool has_flr; bool has_af_flr; + struct hlist_node link; }; struct pci_cfg_ops {