From 5aa92b85ea8a791349a29a0393beb4e6cd293dd4 Mon Sep 17 00:00:00 2001 From: Li Fei1 Date: Thu, 14 Nov 2019 17:58:13 +0800 Subject: [PATCH] hv: vpci: move vBAR base setting into pci_vdev_write_bar Updating vBAR base when setting vBAR configuration sapce. Tracked-On: #3475 Signed-off-by: Li Fei1 --- hypervisor/dm/vpci/pci_pt.c | 42 ++++++++++--------------------- hypervisor/dm/vpci/vdev.c | 45 +++++++++++++++++++++++----------- hypervisor/dm/vpci/vpci_priv.h | 1 - 3 files changed, 44 insertions(+), 44 deletions(-) diff --git a/hypervisor/dm/vpci/pci_pt.c b/hypervisor/dm/vpci/pci_pt.c index 1ac9b7dfb..5767defea 100644 --- a/hypervisor/dm/vpci/pci_pt.c +++ b/hypervisor/dm/vpci/pci_pt.c @@ -49,7 +49,6 @@ static void vdev_pt_unmap_mem_vbar(struct pci_vdev *vdev, uint32_t idx) ept_del_mr(vm, (uint64_t *)(vm->arch_vm.nworld_eptp), vbar->base, /* GPA (old vbar) */ vbar->size); - vbar->base = 0UL; } is_msix_table_bar = (has_msix_cap(vdev) && (idx == vdev->msix.table_bar)); @@ -89,30 +88,16 @@ static void vdev_pt_map_mem_vbar(struct pci_vdev *vdev, uint32_t idx) { bool is_msix_table_bar; struct pci_bar *vbar; - uint64_t vbar_base; struct acrn_vm *vm = vdev->vpci->vm; vbar = &vdev->bar[idx]; - vbar_base = pci_vdev_get_bar_base(vdev, idx); - if (vbar_base != 0UL) { - if (ept_is_mr_valid(vm, vbar_base, vbar->size)) { - uint64_t hpa = gpa2hpa(vdev->vpci->vm, vbar_base); - uint64_t pbar_base = vbar->base_hpa; /* pbar (hpa) */ - - if (hpa != pbar_base) { - ept_add_mr(vm, (uint64_t *)(vm->arch_vm.nworld_eptp), - pbar_base, /* HPA (pbar) */ - vbar_base, /* GPA (new vbar) */ - vbar->size, - EPT_WR | EPT_RD | EPT_UNCACHED); - } - /* Remember the previously mapped MMIO vbar */ - vbar->base = vbar_base; - } else { - pr_fatal("%s, %x:%x.%x set invalid bar[%d] address: 0x%lx\n", __func__, - vdev->bdf.bits.b, vdev->bdf.bits.d, vdev->bdf.bits.f, idx, vbar_base); - } + if (vbar->base != 0UL) { + ept_add_mr(vm, (uint64_t *)(vm->arch_vm.nworld_eptp), + vbar->base_hpa, /* HPA (pbar) */ + vbar->base, /* GPA (new vbar) */ + vbar->size, + EPT_WR | EPT_RD | EPT_UNCACHED); } is_msix_table_bar = (has_msix_cap(vdev) && (idx == vdev->msix.table_bar)); @@ -145,11 +130,8 @@ static void vdev_pt_allow_io_vbar(struct pci_vdev *vdev, uint32_t idx) /* For SOS, all port IO access is allowed by default, so skip SOS here */ if (!is_sos_vm(vdev->vpci->vm)) { struct pci_bar *vbar = &vdev->bar[idx]; - uint64_t vbar_base = pci_vdev_get_bar_base(vdev, idx); /* vbar (gpa) */ - if (vbar_base != 0UL) { - allow_guest_pio_access(vdev->vpci->vm, (uint16_t)vbar_base, (uint32_t)(vbar->size)); - /* Remember the previously allowed IO vbar base */ - vbar->base = vbar_base; + if (vbar->base != 0UL) { + allow_guest_pio_access(vdev->vpci->vm, (uint16_t)vbar->base, (uint32_t)(vbar->size)); } } } @@ -167,7 +149,6 @@ static void vdev_pt_deny_io_vbar(struct pci_vdev *vdev, uint32_t idx) struct pci_bar *vbar = &vdev->bar[idx]; if (vbar->base != 0UL) { deny_guest_pio_access(vdev->vpci->vm, (uint16_t)(vbar->base), (uint32_t)(vbar->size)); - vbar->base = 0UL; } } @@ -190,6 +171,7 @@ void vdev_pt_write_vbar(struct pci_vdev *vdev, uint32_t idx, uint32_t val) vdev_pt_allow_io_vbar(vdev, update_idx); } else { pci_vdev_write_cfg_u32(vdev, offset, val); + vdev->bar[update_idx].base = 0UL; } break; @@ -199,7 +181,7 @@ void vdev_pt_write_vbar(struct pci_vdev *vdev, uint32_t idx, uint32_t val) default: if (vbar->type == PCIBAR_MEM64HI) { - update_idx = idx - 1U; + update_idx -= 1U; } vdev_pt_unmap_mem_vbar(vdev, update_idx); if (val != ~0U) { @@ -207,6 +189,7 @@ void vdev_pt_write_vbar(struct pci_vdev *vdev, uint32_t idx, uint32_t val) vdev_pt_map_mem_vbar(vdev, update_idx); } else { pci_vdev_write_cfg_u32(vdev, offset, val); + vdev->bar[update_idx].base = 0UL; } break; } @@ -280,7 +263,6 @@ void init_vdev_pt(struct pci_vdev *vdev) if (is_prelaunched_vm(vdev->vpci->vm)) { lo = (uint32_t)vdev->pci_dev_config->vbar_base[idx]; } - pci_vdev_write_bar(vdev, idx, lo); if (type == PCIBAR_MEM64) { idx++; @@ -300,12 +282,14 @@ void init_vdev_pt(struct pci_vdev *vdev) if (is_prelaunched_vm(vdev->vpci->vm)) { hi = (uint32_t)(vdev->pci_dev_config->vbar_base[idx - 1U] >> 32U); } + pci_vdev_write_bar(vdev, idx - 1U, lo); pci_vdev_write_bar(vdev, idx, hi); } else { vbar->size = vbar->size & ~(vbar->size - 1UL); if (type == PCIBAR_MEM32) { vbar->size = round_page_up(vbar->size); } + pci_vdev_write_bar(vdev, idx, lo); } } } diff --git a/hypervisor/dm/vpci/vdev.c b/hypervisor/dm/vpci/vdev.c index a90abf737..e8ebd70b8 100644 --- a/hypervisor/dm/vpci/vdev.c +++ b/hypervisor/dm/vpci/vdev.c @@ -29,6 +29,8 @@ #include #include "vpci_priv.h" +#include +#include /** * @pre vdev != NULL @@ -105,24 +107,13 @@ uint32_t pci_vdev_read_bar(const struct pci_vdev *vdev, uint32_t idx) return bar; } -void pci_vdev_write_bar(struct pci_vdev *vdev, uint32_t idx, uint32_t val) +static void pci_vdev_update_bar_base(struct pci_vdev *vdev, uint32_t idx) { struct pci_bar *vbar; - uint32_t bar, offset; - - vbar = &vdev->bar[idx]; - bar = val & vbar->mask; - bar |= vbar->fixed; - offset = pci_bar_offset(idx); - pci_vdev_write_cfg_u32(vdev, offset, bar); -} - -uint64_t pci_vdev_get_bar_base(const struct pci_vdev *vdev, uint32_t idx) -{ - const struct pci_bar *vbar; enum pci_bar_type type; uint64_t base = 0UL; uint32_t lo, hi, offset; + struct acrn_vm *vm = vdev->vpci->vm; vbar = &vdev->bar[idx]; offset = pci_bar_offset(idx); @@ -146,5 +137,31 @@ uint64_t pci_vdev_get_bar_base(const struct pci_vdev *vdev, uint32_t idx) } } - return base; + if ((base != 0UL) && !ept_is_mr_valid(vm, base, vdev->bar[idx].size)) { + pr_fatal("%s, %x:%x.%x set invalid bar[%d] base: 0x%lx, size: 0x%lx\n", __func__, + vdev->bdf.bits.b, vdev->bdf.bits.d, vdev->bdf.bits.f, idx, base, vdev->bar[idx].size); + /* If guest set a invalid GPA, ignore it temporarily */ + base = 0UL; + } + + vdev->bar[idx].base = base; +} + +void pci_vdev_write_bar(struct pci_vdev *vdev, uint32_t idx, uint32_t val) +{ + struct pci_bar *vbar; + uint32_t bar, offset; + uint32_t update_idx = idx; + + vbar = &vdev->bar[idx]; + bar = val & vbar->mask; + bar |= vbar->fixed; + offset = pci_bar_offset(idx); + pci_vdev_write_cfg_u32(vdev, offset, bar); + + if (vbar->type == PCIBAR_MEM64HI) { + update_idx -= 1U; + } + + pci_vdev_update_bar_base(vdev, update_idx); } diff --git a/hypervisor/dm/vpci/vpci_priv.h b/hypervisor/dm/vpci/vpci_priv.h index af520f2fa..03b6c48ea 100644 --- a/hypervisor/dm/vpci/vpci_priv.h +++ b/hypervisor/dm/vpci/vpci_priv.h @@ -146,5 +146,4 @@ struct pci_vdev *pci_find_vdev(struct acrn_vpci *vpci, union pci_bdf vbdf); uint32_t pci_vdev_read_bar(const struct pci_vdev *vdev, uint32_t idx); void pci_vdev_write_bar(struct pci_vdev *vdev, uint32_t idx, uint32_t val); -uint64_t pci_vdev_get_bar_base(const struct pci_vdev *vdev, uint32_t idx); #endif /* VPCI_PRIV_H_ */