HV: add support for PIO bar emulation

For PIO bar emulation, initially or when guest reprograms the PIO bar, allow guest
access for the specified bar base address (pio port) and sized by calling vev_pt_allow_io_vbar

For PIO bar emulation, just set the initial vbar base address equal to pbar
base address. For example, if the pbar base address is 0x2000, then set the
initial vbar base address also to 0x2000

Tracked-On: #3241
Signed-off-by: dongshen <dongsheng.x.zhang@intel.com>
Reviewed-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
dongshen 2019-06-10 18:13:31 -07:00 committed by wenlingz
parent 4be09f24f3
commit 148e747349

View File

@ -30,6 +30,7 @@
#include <errno.h>
#include <ept.h>
#include <mmu.h>
#include <vmx.h>
#include <logmsg.h>
#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;
}
}