diff --git a/hypervisor/hw/pci.c b/hypervisor/hw/pci.c index 77a8dba64..a9ab92547 100644 --- a/hypervisor/hw/pci.c +++ b/hypervisor/hw/pci.c @@ -477,6 +477,31 @@ static inline uint32_t pci_pdev_get_nr_bars(uint8_t hdr_type) return nr_bars; } +/** + * @pre pdev != NULL + */ +static void pci_read_ext_cap(struct pci_pdev *pdev) { + + uint32_t hdr, pos; + + pos = PCI_ECAP_BASE_PTR; + + /* PCI Express Extended Capability must have 4 bytes header */ + hdr = pci_pdev_read_cfg(pdev->bdf, pos, 4U); + while (hdr != 0U) { + if (PCI_ECAP_ID(hdr) == PCIZ_SRIOV) { + pdev->sriov.capoff = pos; + pdev->sriov.caplen = PCI_SRIOV_CAP_LEN; + } + pos = PCI_ECAP_NEXT(hdr); + if (pos == 0U) { + break; + } + + hdr = pci_pdev_read_cfg(pdev->bdf, pos, 4U); + }; +} + /* * @pre pdev != NULL */ @@ -487,6 +512,7 @@ static void pci_read_cap(struct pci_pdev *pdev) uint32_t len, idx; uint32_t table_info; uint32_t pcie_devcap, val; + bool is_pcie = false; pos = (uint8_t)pci_pdev_read_cfg(pdev->bdf, PCIR_CAP_PTR, 1U); @@ -520,6 +546,7 @@ static void pci_read_cap(struct pci_pdev *pdev) val = pci_pdev_read_cfg(pdev->bdf, pos + PCIR_PMCSR, 4U); pdev->has_pm_reset = ((val & PCIM_PMCSR_NO_SOFT_RST) == 0U); } else if (cap == PCIY_PCIE) { + is_pcie = true; pcie_devcap = pci_pdev_read_cfg(pdev->bdf, pos + PCIR_PCIE_DEVCAP, 4U); pdev->has_flr = ((pcie_devcap & PCIM_PCIE_FLRCAP) != 0U); } else if (cap == PCIY_AF) { @@ -531,6 +558,10 @@ static void pci_read_cap(struct pci_pdev *pdev) pos = (uint8_t)pci_pdev_read_cfg(pdev->bdf, pos + PCICAP_NEXTPTR, 1U); } + + if (is_pcie) { + pci_read_ext_cap(pdev); + } } static void init_pdev(uint16_t pbdf, uint32_t drhd_index) diff --git a/hypervisor/include/hw/pci.h b/hypervisor/include/hw/pci.h index eede09a82..de78e0e47 100644 --- a/hypervisor/include/hw/pci.h +++ b/hypervisor/include/hw/pci.h @@ -106,6 +106,15 @@ #define PCIY_MSI 0x05U #define PCIY_MSIX 0x11U +/* PCIe Extended Capability*/ +#define PCI_ECAP_BASE_PTR 0x100U +#define PCI_ECAP_ID(hdr) ((uint32_t)((hdr) & 0xFFFFU)) +#define PCI_ECAP_NEXT(hdr) ((uint32_t)(((hdr) >> 20U) & 0xFFCU)) +#define PCIZ_SRIOV 0x10U + +/* SRIOV Definitions */ +#define PCI_SRIOV_CAP_LEN 0x40U + /* PCI Message Signalled Interrupts (MSI) */ #define PCIR_MSI_CTRL 0x02U #define PCIM_MSICTRL_64BIT 0x80U @@ -192,6 +201,11 @@ struct pci_msix_cap { uint8_t cap[MSIX_CAPLEN]; }; +struct pci_sriov_cap { + uint32_t capoff; + uint32_t caplen; +}; + struct pci_pdev { uint8_t hdr_type; @@ -208,6 +222,7 @@ struct pci_pdev { uint32_t msi_capoff; struct pci_msix_cap msix; + struct pci_sriov_cap sriov; bool has_pm_reset; bool has_flr;