From ab4e19d0be3330d18b1ffe761a5b62887afedcb1 Mon Sep 17 00:00:00 2001 From: Fei Li Date: Wed, 7 Sep 2022 11:24:04 +0800 Subject: [PATCH] hv: vPCI: fix large bar base update The current code would write 'BAR address & size_maks' into PCIe virtual BAR before updating the virtual BAR's base address when guest writing a PCIe device's BAR. If the size of a PCIe device's BAR is larger than 4G, the low 32 bits size_mask for this 64 bits BAR is zero. When ACRN updating the virtual BAR's base address, the low 32 bits sizing information would be lost. This patch saves whether a BAR writing is sizing or not before updating the virtual BAR's base address. Tracked-On: #8267 Signed-off-by: Fei Li --- hypervisor/dm/vpci/vdev.c | 7 ++++--- hypervisor/include/dm/vpci.h | 1 + 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/hypervisor/dm/vpci/vdev.c b/hypervisor/dm/vpci/vdev.c index e1c45de27..7afa85bed 100644 --- a/hypervisor/dm/vpci/vdev.c +++ b/hypervisor/dm/vpci/vdev.c @@ -111,13 +111,13 @@ static void pci_vdev_update_vbar_base(struct pci_vdev *vdev, uint32_t idx) vbar = &vdev->vbars[idx]; offset = pci_bar_offset(idx); lo = pci_vdev_read_vcfg(vdev, offset, 4U); - if ((!is_pci_reserved_bar(vbar)) && (lo != (vbar->mask | vbar->bar_type.bits))) { + if ((!is_pci_reserved_bar(vbar)) && !vbar->sizing) { base = lo & vbar->mask; if (is_pci_mem64lo_bar(vbar)) { vbar = &vdev->vbars[idx + 1U]; - hi = pci_vdev_read_vcfg(vdev, (offset + 4U), 4U); - if (hi != vbar->mask) { + if (!vbar->sizing) { + hi = pci_vdev_read_vcfg(vdev, (offset + 4U), 4U); base |= ((uint64_t)hi << 32U); } else { base = 0UL; @@ -199,6 +199,7 @@ void pci_vdev_write_vbar(struct pci_vdev *vdev, uint32_t idx, uint32_t val) uint32_t update_idx = idx; vbar = &vdev->vbars[idx]; + vbar->sizing = (val == ~0U); bar = val & vbar->mask; if (vbar->is_mem64hi) { update_idx -= 1U; diff --git a/hypervisor/include/dm/vpci.h b/hypervisor/include/dm/vpci.h index 6826ab361..45a1c7ca4 100644 --- a/hypervisor/include/dm/vpci.h +++ b/hypervisor/include/dm/vpci.h @@ -38,6 +38,7 @@ struct pci_vbar { bool is_mem64hi; /* this is to indicate the high part of 64 bits MMIO bar */ + bool sizing; /* this is to indicate the guest is sizing this BAR */ uint64_t size; /* BAR size */ uint64_t base_gpa; /* BAR guest physical address */ uint64_t base_hpa; /* BAR host physical address */