diff --git a/hypervisor/dm/vpci/pci_pt.c b/hypervisor/dm/vpci/pci_pt.c index 5874c7702..e28104030 100644 --- a/hypervisor/dm/vpci/pci_pt.c +++ b/hypervisor/dm/vpci/pci_pt.c @@ -315,6 +315,53 @@ void vdev_pt_write_vbar(struct pci_vdev *vdev, uint32_t idx, uint32_t val) } } +/* + * @pre vdev != NULL + * @pre vdev->pdev != NULL + */ +void vdev_bridge_pt_restore_space(struct pci_vdev *vdev) +{ + struct pci_pdev *pdev = vdev->pdev; + uint32_t pre_val; + uint32_t offset; + + /* I/O Base (0x1c) and I/O Limit (0x1d) */ + pre_val = pci_vdev_read_vcfg(vdev, PCIR_IO_BASE, 2U); + if (pre_val != pci_pdev_read_cfg(vdev->pdev->bdf, PCIR_IO_BASE, 2U)) { + pci_pdev_write_cfg(pdev->bdf, PCIR_IO_BASE, 2U, pre_val); + } + + /* From Memory Base (0x20) to I/O Base Limit 16 Bits (0x32) */ + for (offset = PCIR_MEM_BASE; offset < PCIR_IO_BASE_UPPER_16; offset += 4) { + pre_val = pci_vdev_read_vcfg(vdev, offset, 4U); + if (pre_val != pci_pdev_read_cfg(vdev->pdev->bdf, offset, 4U)) { + pci_pdev_write_cfg(pdev->bdf, offset, 4U, pre_val); + } + } +} + +/* + * @pre vdev != NULL + * @pre vdev->pdev != NULL + */ +void vdev_bridge_pt_restore_bus(struct pci_vdev *vdev) +{ + struct pci_pdev *pdev = vdev->pdev; + uint32_t pre_val; + + /* Primary Bus Number (0x18) and Secondary Bus Number (0x19) */ + pre_val = pci_vdev_read_vcfg(vdev, PCIR_PRIBUS_1, 2U); + if (pre_val != pci_pdev_read_cfg(vdev->pdev->bdf, PCIR_PRIBUS_1, 2U)) { + pci_pdev_write_cfg(pdev->bdf, PCIR_PRIBUS_1, 2U, pre_val); + } + + /* Subordinate Bus Number (0x1a) */ + pre_val = pci_vdev_read_vcfg(vdev, PCIR_SUBBUS_1, 1U); + if (pre_val != pci_pdev_read_cfg(vdev->pdev->bdf, PCIR_SUBBUS_1, 1U)) { + pci_pdev_write_cfg(pdev->bdf, PCIR_SUBBUS_1, 1U, pre_val); + } +} + /** * PCI base address register (bar) virtualization: * diff --git a/hypervisor/dm/vpci/vpci.c b/hypervisor/dm/vpci/vpci.c index ad475d9e7..259c6168f 100644 --- a/hypervisor/dm/vpci/vpci.c +++ b/hypervisor/dm/vpci/vpci.c @@ -474,6 +474,7 @@ static int32_t read_cfg_header(const struct pci_vdev *vdev, static int32_t write_cfg_header(struct pci_vdev *vdev, uint32_t offset, uint32_t bytes, uint32_t val) { + bool dev_is_bridge = is_bridge(vdev->pdev); int32_t ret = 0; if ((offset == PCIR_BIOS) && is_quirk_ptdev(vdev)) { @@ -489,10 +490,20 @@ static int32_t write_cfg_header(struct pci_vdev *vdev, #define PCIM_SPACE_EN (PCIM_CMD_PORTEN | PCIM_CMD_MEMEN) uint16_t phys_cmd = (uint16_t)pci_pdev_read_cfg(vdev->pdev->bdf, PCIR_COMMAND, 2U); - /* check whether need to restore BAR because some kind of reset */ - if (((phys_cmd & PCIM_SPACE_EN) == 0U) && ((val & PCIM_SPACE_EN) != 0U) && - pdev_need_bar_restore(vdev->pdev)) { - pdev_restore_bar(vdev->pdev); + if (((phys_cmd & PCIM_SPACE_EN) == 0U) && ((val & PCIM_SPACE_EN) != 0U)) { + /* check whether need to restore BAR because some kind of reset */ + if (pdev_need_bar_restore(vdev->pdev)) { + pdev_restore_bar(vdev->pdev); + } + + /* check whether need to restore bridge mem/IO related registers because some kind of reset */ + if (dev_is_bridge) { + vdev_bridge_pt_restore_space(vdev); + } + } + /* check whether need to restore Primary/Secondary/Subordinate Bus Number registers because some kind of reset */ + if (dev_is_bridge && ((phys_cmd & PCIM_CMD_BUSEN) == 0U) && ((val & PCIM_CMD_BUSEN) != 0U)) { + vdev_bridge_pt_restore_bus(vdev); } } diff --git a/hypervisor/dm/vpci/vpci_priv.h b/hypervisor/dm/vpci/vpci_priv.h index 0094de815..d89689c91 100644 --- a/hypervisor/dm/vpci/vpci_priv.h +++ b/hypervisor/dm/vpci/vpci_priv.h @@ -177,6 +177,9 @@ uint32_t vpci_add_capability(struct pci_vdev *vdev, uint8_t *capdata, uint8_t ca void pci_vdev_write_vbar(struct pci_vdev *vdev, uint32_t idx, uint32_t val); +void vdev_bridge_pt_restore_space(struct pci_vdev *vdev); +void vdev_bridge_pt_restore_bus(struct pci_vdev *vdev); + void vdev_pt_hide_sriov_cap(struct pci_vdev *vdev); int32_t check_pt_dev_pio_bars(struct pci_vdev *vdev); diff --git a/hypervisor/include/hw/pci.h b/hypervisor/include/hw/pci.h index 9903e900a..83b23f54e 100644 --- a/hypervisor/include/hw/pci.h +++ b/hypervisor/include/hw/pci.h @@ -69,6 +69,7 @@ #define PCIR_COMMAND 0x04U #define PCIM_CMD_PORTEN 0x01U #define PCIM_CMD_MEMEN 0x02U +#define PCIM_CMD_BUSEN 0x04U #define PCIM_CMD_INTxDIS 0x400U #define PCIR_STATUS 0x06U #define PCIM_STATUS_CAPPRESENT 0x0010U @@ -105,6 +106,9 @@ #define PCIR_PRIBUS_1 0x18U #define PCIR_SECBUS_1 0x19U #define PCIR_SUBBUS_1 0x1AU +#define PCIR_IO_BASE 0x1CU +#define PCIR_MEM_BASE 0x20U +#define PCIR_IO_BASE_UPPER_16 0x30U /* Capability Register Offsets */ #define PCICAP_ID 0x0U