diff --git a/hypervisor/dm/vpci/pci_pt.c b/hypervisor/dm/vpci/pci_pt.c index 0fc3112bc..4928a5723 100644 --- a/hypervisor/dm/vpci/pci_pt.c +++ b/hypervisor/dm/vpci/pci_pt.c @@ -305,6 +305,22 @@ static void vdev_pt_remap_generic_mem_vbar(struct pci_vdev *vdev, uint32_t idx) } } +/** + * @pre vdev != NULL + */ +static void vdev_pt_remap_mem_vbar(struct pci_vdev *vdev, uint32_t idx) +{ + bool is_msix_table_bar; + + is_msix_table_bar = (has_msix_cap(vdev) && (idx == vdev->msix.table_bar)); + + if (is_msix_table_bar) { + vdev_pt_remap_msix_table_bar(vdev); + } else { + vdev_pt_remap_generic_mem_vbar(vdev, idx); + } +} + /** * @brief Set the base address portion of the vbar base address register (32-bit) * base: bar value with flags portion masked off @@ -335,30 +351,26 @@ static void set_vbar_base(struct pci_bar *vbar, uint32_t base) static void vdev_pt_write_vbar(struct pci_vdev *vdev, uint32_t offset, uint32_t val) { uint32_t idx; - uint32_t base, mask; + uint64_t base; bool bar_update_normal; - bool is_msix_table_bar; + struct pci_bar *vbar; - base = 0U; + base = 0UL; idx = (offset - pci_bar_offset(0U)) >> 2U; - mask = ~(vdev->bar[idx].size - 1U); + bar_update_normal = (val != (uint32_t)~0U); + + vbar = &vdev->bar[idx]; switch (vdev->bar[idx].type) { case PCIBAR_NONE: break; case PCIBAR_MEM32: - bar_update_normal = (val != (uint32_t)~0U); - is_msix_table_bar = (has_msix_cap(vdev) && (idx == vdev->msix.table_bar)); - base = val & mask; - set_vbar_base(&vdev->bar[idx], base); + base = pci_base_from_size_mask(vbar->size, (uint64_t)val); + set_vbar_base(vbar, (uint32_t)base); if (bar_update_normal) { - if (is_msix_table_bar) { - vdev_pt_remap_msix_table_bar(vdev); - } else { - vdev_pt_remap_generic_mem_vbar(vdev, idx); - } + vdev_pt_remap_mem_vbar(vdev, idx); } break; @@ -368,7 +380,7 @@ static void vdev_pt_write_vbar(struct pci_vdev *vdev, uint32_t offset, uint32_t } /* Write the vbar value to corresponding virtualized vbar reg */ - pci_vdev_write_cfg_u32(vdev, offset, vdev->bar[idx].reg.value); + pci_vdev_write_cfg_u32(vdev, offset, vbar->reg.value); } /** diff --git a/hypervisor/include/hw/pci.h b/hypervisor/include/hw/pci.h index 7b7944d68..cd4da263b 100644 --- a/hypervisor/include/hw/pci.h +++ b/hypervisor/include/hw/pci.h @@ -266,6 +266,19 @@ static inline enum pci_bar_type pci_get_bar_type(uint32_t val) return type; } +/** + * Given bar size and raw bar value, return bar base address by masking off its lower flag bits + * size/val: all in 64-bit values to accommodate 64-bit MMIO bar size masking + */ +static inline uint64_t pci_base_from_size_mask(uint64_t size, uint64_t val) +{ + uint64_t mask; + + mask = ~(size - 1UL); + + return (mask & val); +} + static inline uint8_t pci_bus(uint16_t bdf) { return (uint8_t)((bdf >> 8U) & 0xFFU);