diff --git a/hypervisor/dm/vpci/pci_pt.c b/hypervisor/dm/vpci/pci_pt.c index 124eb056e..424869019 100644 --- a/hypervisor/dm/vpci/pci_pt.c +++ b/hypervisor/dm/vpci/pci_pt.c @@ -235,6 +235,8 @@ void init_vdev_pt(struct pci_vdev *vdev) vdev->has_flr = vdev->pdev->has_flr; vdev->pcie_capoff = vdev->pdev->pcie_capoff; + vdev->has_af_flr = vdev->pdev->has_af_flr; + vdev->af_capoff = vdev->pdev->af_capoff; for (idx = 0U; idx < vdev->nr_bars; idx++) { vbar = &vdev->bar[idx]; diff --git a/hypervisor/dm/vpci/vpci.c b/hypervisor/dm/vpci/vpci.c index 9f146653b..561bf4c98 100644 --- a/hypervisor/dm/vpci/vpci.c +++ b/hypervisor/dm/vpci/vpci.c @@ -337,8 +337,9 @@ static int32_t vpci_write_pt_dev_cfg(struct pci_vdev *vdev, uint32_t offset, vmsi_write_cfg(vdev, offset, bytes, val); } else if (msixcap_access(vdev, offset)) { vmsix_write_cfg(vdev, offset, bytes, val); - } else if (vdev->has_flr && ((vdev->pcie_capoff + PCIR_PCIE_DEVCTRL) == offset) && - ((val & PCIM_PCIE_FLR) != 0U)) { + } else if ((vdev->has_flr && ((vdev->pcie_capoff + PCIR_PCIE_DEVCTRL) == offset) && + ((val & PCIM_PCIE_FLR) != 0U)) || (vdev->has_af_flr && + ((vdev->af_capoff + PCIR_AF_CTRL) == offset) && ((val & PCIM_AF_FLR) != 0U))) { /* Assume that guest write FLR must be 4 bytes aligned */ pdev_do_flr(vdev->pdev->bdf, offset, bytes, val); } else { diff --git a/hypervisor/hw/pci.c b/hypervisor/hw/pci.c index 1da24fcdb..f364cab51 100644 --- a/hypervisor/hw/pci.c +++ b/hypervisor/hw/pci.c @@ -418,7 +418,7 @@ static void pci_read_cap(struct pci_pdev *pdev) uint32_t msgctrl; uint32_t len, offset, idx; uint32_t table_info; - uint32_t pcie_devcap; + uint32_t pcie_devcap, val; ptr = (uint8_t)pci_pdev_read_cfg(pdev->bdf, PCIR_CAP_PTR, 1U); @@ -426,7 +426,7 @@ static void pci_read_cap(struct pci_pdev *pdev) cap = (uint8_t)pci_pdev_read_cfg(pdev->bdf, ptr + PCICAP_ID, 1U); /* Ignore all other Capability IDs for now */ - if ((cap == PCIY_MSI) || (cap == PCIY_MSIX) || (cap == PCIY_PCIE)) { + if ((cap == PCIY_MSI) || (cap == PCIY_MSIX) || (cap == PCIY_PCIE) || (cap == PCIY_AF)) { offset = ptr; if (cap == PCIY_MSI) { pdev->msi_capoff = offset; @@ -451,11 +451,16 @@ static void pci_read_cap(struct pci_pdev *pdev) for (idx = 0U; idx < len; idx++) { pdev->msix.cap[idx] = (uint8_t)pci_pdev_read_cfg(pdev->bdf, offset + idx, 1U); } - } else { + } else if (cap == PCIY_PCIE) { /* PCI Express Capability */ pdev->pcie_capoff = offset; pcie_devcap = pci_pdev_read_cfg(pdev->bdf, offset + PCIR_PCIE_DEVCAP, 4U); pdev->has_flr = ((pcie_devcap & PCIM_PCIE_FLRCAP) != 0U) ? true : false; + } else { + /* Conventional PCI Advanced Features Capability */ + pdev->af_capoff = offset; + val = pci_pdev_read_cfg(pdev->bdf, offset, 4U); + pdev->has_af_flr = ((val & PCIM_AF_FLR_CAP) != 0U) ? true : false; } } diff --git a/hypervisor/include/dm/vpci.h b/hypervisor/include/dm/vpci.h index 1e3642417..dfe970962 100644 --- a/hypervisor/include/dm/vpci.h +++ b/hypervisor/include/dm/vpci.h @@ -102,6 +102,9 @@ struct pci_vdev { bool has_flr; uint32_t pcie_capoff; + bool has_af_flr; + uint32_t af_capoff; + /* Pointer to corresponding PCI device's vm_config */ struct acrn_vm_pci_dev_config *pci_dev_config; diff --git a/hypervisor/include/hw/pci.h b/hypervisor/include/hw/pci.h index 95dd936dc..a43aeaa54 100644 --- a/hypervisor/include/hw/pci.h +++ b/hypervisor/include/hw/pci.h @@ -138,6 +138,12 @@ #define PCIM_PCIE_FLRCAP (0x1U << 28U) #define PCIM_PCIE_FLR (0x1U << 15U) +/* Conventional PCI Advanced Features Capability */ +#define PCIY_AF 0x13U +#define PCIM_AF_FLR_CAP (0x1U << 25U) +#define PCIR_AF_CTRL 0x4U +#define PCIM_AF_FLR 0x1U + #define HOST_BRIDGE_BDF 0U #define PCI_STD_NUM_BARS 6U @@ -189,6 +195,10 @@ struct pci_pdev { /* Function Level Reset Capability */ bool has_flr; uint32_t pcie_capoff; + + /* Conventional PCI Advanced Features FLR Capability */ + bool has_af_flr; + uint32_t af_capoff; }; static inline uint32_t pci_bar_offset(uint32_t idx)