Signed-off-by: Clement Mathieu--Drif <clement.mathieu--d...@eviden.com> --- hw/pci/pcie.c | 26 ++++++++++++++++++++++++++ include/hw/pci/pcie.h | 5 ++++- include/hw/pci/pcie_regs.h | 3 +++ 3 files changed, 33 insertions(+), 1 deletion(-)
diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c index 36de709801..542172b3fa 100644 --- a/hw/pci/pcie.c +++ b/hw/pci/pcie.c @@ -1240,6 +1240,32 @@ void pcie_pasid_init(PCIDevice *dev, uint16_t offset, uint8_t pasid_width, dev->exp.pasid_cap = offset; } +/* PRI */ +void pcie_pri_init(PCIDevice *dev, uint16_t offset, uint32_t outstanding_pr_cap, + bool prg_response_pasid_req) +{ + static const uint16_t control_reg_rw_mask = 0x3; + static const uint16_t status_reg_rw1_mask = 0x3; + static const uint32_t pr_alloc_reg_rw_mask = 0xffffffff; + uint16_t status_reg; + + status_reg = prg_response_pasid_req ? PCI_PRI_STATUS_PASID : 0; + status_reg |= PCI_PRI_STATUS_STOPPED; /* Stopped by default */ + + pcie_add_capability(dev, PCI_EXT_CAP_ID_PRI, PCI_PRI_VER, offset, + PCI_EXT_CAP_PRI_SIZEOF); + /* Disabled by default */ + + pci_set_word(dev->config + offset + PCI_PRI_STATUS, status_reg); + pci_set_long(dev->config + offset + PCI_PRI_MAX_REQ, outstanding_pr_cap); + + pci_set_word(dev->wmask + offset + PCI_PRI_CTRL, control_reg_rw_mask); + pci_set_word(dev->w1cmask + offset + PCI_PRI_STATUS, status_reg_rw1_mask); + pci_set_long(dev->wmask + offset + PCI_PRI_ALLOC_REQ, pr_alloc_reg_rw_mask); + + dev->exp.pri_cap = offset; +} + bool pcie_pasid_enabled(const PCIDevice *dev) { if (!pci_is_express(dev) || !dev->exp.pasid_cap) { diff --git a/include/hw/pci/pcie.h b/include/hw/pci/pcie.h index 497d0bc2d2..17f06cd5d6 100644 --- a/include/hw/pci/pcie.h +++ b/include/hw/pci/pcie.h @@ -70,9 +70,10 @@ struct PCIExpressDevice { uint16_t aer_cap; PCIEAERLog aer_log; - /* Offset of ATS and PASID capabilities in config space */ + /* Offset of ATS, PRI and PASID capabilities in config space */ uint16_t ats_cap; uint16_t pasid_cap; + uint16_t pri_cap; /* ACS */ uint16_t acs_cap; @@ -154,6 +155,8 @@ void pcie_cap_slot_unplug_request_cb(HotplugHandler *hotplug_dev, void pcie_pasid_init(PCIDevice *dev, uint16_t offset, uint8_t pasid_width, bool exec_perm, bool priv_mod); +void pcie_pri_init(PCIDevice *dev, uint16_t offset, uint32_t outstanding_pr_cap, + bool prg_response_pasid_req); bool pcie_pasid_enabled(const PCIDevice *dev); bool pcie_ats_enabled(const PCIDevice *dev); diff --git a/include/hw/pci/pcie_regs.h b/include/hw/pci/pcie_regs.h index 4d9cf4a29c..33a22229fe 100644 --- a/include/hw/pci/pcie_regs.h +++ b/include/hw/pci/pcie_regs.h @@ -91,6 +91,9 @@ typedef enum PCIExpLinkWidth { #define PCI_EXT_CAP_PASID_MAX_WIDTH 20 #define PCI_PASID_CAP_WIDTH_SHIFT 8 +/* PRI */ +#define PCI_PRI_VER 1 + /* AER */ #define PCI_ERR_VER 2 #define PCI_ERR_SIZEOF 0x48 -- 2.49.0