diff --git a/hypervisor/dm/vpci/pci_pt.c b/hypervisor/dm/vpci/pci_pt.c index 3c89d3b0a..faab74a39 100644 --- a/hypervisor/dm/vpci/pci_pt.c +++ b/hypervisor/dm/vpci/pci_pt.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include "vpci_priv.h" @@ -319,6 +320,33 @@ static void vdev_pt_remap_mem_vbar(struct pci_vdev *vdev, uint32_t idx) } } +/** + * @brief Allow IO bar access + * @pre vdev != NULL + * @pre vdev->vpci != NULL + * @pre vdev->vpci->vm != NULL + */ +static void vdev_pt_allow_io_vbar(struct pci_vdev *vdev, uint32_t idx) +{ + struct pci_bar *vbar; + uint64_t vbar_base = get_vbar_base(vdev, idx); /* vbar (gpa) */ + + vbar = &vdev->bar[idx]; + + /* For SOS, all port IO access is allowed by default, so skip SOS here */ + if ((vdev->bar_base_mapped[idx] != vbar_base) && !is_sos_vm(vdev->vpci->vm)) { + if (vdev->bar_base_mapped[idx] != 0UL) { + deny_guest_pio_access(vdev->vpci->vm, (uint16_t)(vdev->bar_base_mapped[idx]), + (uint32_t)(vbar->size)); + } + + allow_guest_pio_access(vdev->vpci->vm, (uint16_t)vbar_base, (uint32_t)(vbar->size)); + + /* Remember the previously allowed IO vbar base */ + vdev->bar_base_mapped[idx] = vbar_base; + } +} + /** * @brief Set the base address portion of the vbar base address register (32-bit) * base: bar value with flags portion masked off @@ -375,6 +403,15 @@ static void vdev_pt_write_vbar(struct pci_vdev *vdev, uint32_t offset, uint32_t enum pci_bar_type type = pci_get_bar_type(vbar->reg.value); switch (type) { + case PCIBAR_IO_SPACE: + base = git_size_masked_bar_base(vbar->size, (uint64_t)val) & 0xffffUL; + set_vbar_base(vbar, (uint32_t)base); + + if (bar_update_normal) { + vdev_pt_allow_io_vbar(vdev, idx); + } + break; + case PCIBAR_MEM32: base = git_size_masked_bar_base(vbar->size, (uint64_t)val); set_vbar_base(vbar, (uint32_t)base); @@ -497,9 +534,13 @@ void init_vdev_pt(struct pci_vdev *vdev) vdev_pt_write_vbar(vdev, pci_bar_offset(idx), (uint32_t)vbar_base); break; + case PCIBAR_IO_SPACE: + vbar->size = pbar->size; + vdev_pt_write_vbar(vdev, pci_bar_offset(idx), (uint32_t)get_pbar_base(vdev->pdev, idx)); + break; + default: - vbar->reg.value = 0x0U; - vbar->size = 0UL; + /* Nothing to do in this case */ break; } }