hv: fix bug in sizing MSI-X Table Base Address Register

To sizing a 64-bit BAR, need to form the two 32-bit registers as a
64-bit words, before doing the calculation: inverting all bits and
incrementing by 1.

Tracked-On: #1568
Signed-off-by: dongshen <dongsheng.x.zhang@intel.com>
Signed-off-by: Zide Chen <zide.chen@intel.com>
Acked-by: Anthony Xu <anthony.xu@intel.com>
This commit is contained in:
Zide Chen 2018-10-29 08:38:02 -07:00 committed by Xie, Nanlin
parent 51977a6d2c
commit 5555a2f85d

View File

@ -261,7 +261,7 @@ static void decode_msix_table_bar(struct pci_vdev *vdev)
uint32_t bir = vdev->msix.table_bar; uint32_t bir = vdev->msix.table_bar;
union pci_bdf pbdf = vdev->pdev.bdf; union pci_bdf pbdf = vdev->pdev.bdf;
uint64_t base, size; uint64_t base, size;
uint32_t bar_lo, bar_hi; uint32_t bar_lo, bar_hi, val32;
bar_lo = pci_pdev_read_cfg(pbdf, pci_bar_offset(bir), 4U); bar_lo = pci_pdev_read_cfg(pbdf, pci_bar_offset(bir), 4U);
if ((bar_lo & PCIM_BAR_SPACE) == PCIM_BAR_IO_SPACE) { if ((bar_lo & PCIM_BAR_SPACE) == PCIM_BAR_IO_SPACE) {
@ -281,16 +281,19 @@ static void decode_msix_table_bar(struct pci_vdev *vdev)
vdev->msix.mmio_gpa = vm0_hpa2gpa(base); vdev->msix.mmio_gpa = vm0_hpa2gpa(base);
/* Sizing the BAR */ /* Sizing the BAR */
pci_pdev_write_cfg(pbdf, pci_bar_offset(bir), 4U, ~0U); size = 0U;
size = pci_pdev_read_cfg(pbdf, pci_bar_offset(bir), 4U); if (((bar_lo & PCIM_BAR_MEM_TYPE) == PCIM_BAR_MEM_64) && (bir < (PCI_BAR_COUNT - 1U))) {
vdev->msix.mmio_size = (size & ~(size - 1U));
if ((bar_lo & PCIM_BAR_MEM_TYPE) == PCIM_BAR_MEM_64) {
pci_pdev_write_cfg(pbdf, pci_bar_offset(bir + 1U), 4U, ~0U); pci_pdev_write_cfg(pbdf, pci_bar_offset(bir + 1U), 4U, ~0U);
size = (uint64_t)pci_pdev_read_cfg(pbdf, pci_bar_offset(bir + 1U), 4U); size = (uint64_t)pci_pdev_read_cfg(pbdf, pci_bar_offset(bir + 1U), 4U);
vdev->msix.mmio_size |= (size << 32U); size <<= 32U;
} }
pci_pdev_write_cfg(pbdf, pci_bar_offset(bir), 4U, ~0U);
val32 = pci_pdev_read_cfg(pbdf, pci_bar_offset(bir), 4U);
size |= ((uint64_t)val32 & PCIM_BAR_MEM_BASE);
vdev->msix.mmio_size = size & ~(size - 1U);
/* Restore the BAR */ /* Restore the BAR */
pci_pdev_write_cfg(pbdf, pci_bar_offset(bir), 4U, bar_lo); pci_pdev_write_cfg(pbdf, pci_bar_offset(bir), 4U, bar_lo);
@ -314,6 +317,12 @@ static int vmsix_init(struct pci_vdev *vdev)
msix->table_offset = table_info & ~PCIM_MSIX_BIR_MASK; msix->table_offset = table_info & ~PCIM_MSIX_BIR_MASK;
msix->table_count = (msgctrl & PCIM_MSIXCTRL_TABLE_SIZE) + 1U; msix->table_count = (msgctrl & PCIM_MSIXCTRL_TABLE_SIZE) + 1U;
if (msix->table_bar >= (PCI_BAR_COUNT - 1U)) {
pr_err("%s, MSI-X device (%x) invalid table BIR %d", __func__, vdev->pdev.bdf.value, msix->table_bar);
vdev->msix.capoff = 0U;
return -EIO;
}
/* Mask all table entries */ /* Mask all table entries */
for (i = 0U; i < msix->table_count; i++) { for (i = 0U; i < msix->table_count; i++) {
msix->tables[i].vector_control |= PCIM_MSIX_VCTRL_MASK; msix->tables[i].vector_control |= PCIM_MSIX_VCTRL_MASK;