dm: pci: update MMIO EPT mapping when update BAR address

For PCI passthrough device when guest OS updates the BAR address
the corresponding EPT mapping should be updated as well.

Tracked-On: #2962
Signed-off-by: Jian Jun Chen <jian.jun.chen@intel.com>
Signed-off-by: Liu Shuo A <shuo.a.liu@intel.com>
Reviewed-by: Binbin Wu <binbin.wu@intel.com>
Acked-by: Yin Fengwei <fengwei.yin@intel.com>
This commit is contained in:
Jian Jun Chen 2019-05-22 13:41:36 +08:00 committed by wenlingz
parent cee2f8b288
commit 811d1fe93d
3 changed files with 50 additions and 5 deletions

View File

@ -594,9 +594,11 @@ memen(struct pci_vdev *dev)
* the address range decoded by the BAR register.
*/
static void
update_bar_address(struct pci_vdev *dev, uint64_t addr, int idx, int type)
update_bar_address(struct vmctx *ctx, struct pci_vdev *dev, uint64_t addr,
int idx, int type)
{
bool decode;
uint64_t orig_addr = dev->bar[idx].addr;
if (dev->bar[idx].type == PCIBAR_IO)
decode = porten(dev);
@ -625,6 +627,10 @@ update_bar_address(struct pci_vdev *dev, uint64_t addr, int idx, int type)
if (decode)
register_bar(dev, idx);
/* update bar mapping */
if (dev->dev_ops->vdev_update_bar_map)
dev->dev_ops->vdev_update_bar_map(ctx, dev, idx, orig_addr);
}
int
@ -2136,7 +2142,7 @@ pci_cfgrw(struct vmctx *ctx, int vcpu, int in, int bus, int slot, int func,
* Register the new BAR value for interception
*/
if (addr != dev->bar[idx].addr) {
update_bar_address(dev, addr, idx,
update_bar_address(ctx, dev, addr, idx,
PCIBAR_IO);
}
break;
@ -2144,7 +2150,7 @@ pci_cfgrw(struct vmctx *ctx, int vcpu, int in, int bus, int slot, int func,
addr = bar = *eax & mask;
bar |= PCIM_BAR_MEM_SPACE | PCIM_BAR_MEM_32;
if (addr != dev->bar[idx].addr) {
update_bar_address(dev, addr, idx,
update_bar_address(ctx, dev, addr, idx,
PCIBAR_MEM32);
}
break;
@ -2153,7 +2159,7 @@ pci_cfgrw(struct vmctx *ctx, int vcpu, int in, int bus, int slot, int func,
bar |= PCIM_BAR_MEM_SPACE | PCIM_BAR_MEM_64 |
PCIM_BAR_MEM_PREFETCH;
if (addr != (uint32_t)dev->bar[idx].addr) {
update_bar_address(dev, addr, idx,
update_bar_address(ctx, dev, addr, idx,
PCIBAR_MEM64);
}
break;
@ -2163,7 +2169,7 @@ pci_cfgrw(struct vmctx *ctx, int vcpu, int in, int bus, int slot, int func,
addr = ((uint64_t)*eax << 32) & mask;
bar = addr >> 32;
if (bar != dev->bar[idx - 1].addr >> 32) {
update_bar_address(dev, addr, idx - 1,
update_bar_address(ctx, dev, addr, idx - 1,
PCIBAR_MEMHI64);
}
break;

View File

@ -938,6 +938,39 @@ passthru_deinit(struct vmctx *ctx, struct pci_vdev *dev, char *opts)
vm_unassign_ptdev(ctx, bus, slot, func);
}
static void
passthru_update_bar_map(struct vmctx *ctx, struct pci_vdev *dev,
int idx, uint64_t orig_addr)
{
struct passthru_dev *ptdev;
if (!dev->arg) {
warnx("%s: passthru_dev is NULL", __func__);
return;
}
ptdev = (struct passthru_dev *)dev->arg;
if (ptdev->bar[idx].size == 0 ||
idx == ptdev_msix_table_bar(ptdev) ||
ptdev->bar[idx].type == PCIBAR_IO)
return;
if (dev->bar[idx].addr + dev->bar[idx].size > PCI_EMUL_MEMLIMIT64 ||
orig_addr + dev->bar[idx].size > PCI_EMUL_MEMLIMIT64)
return;
vm_unmap_ptdev_mmio(ctx, ptdev->sel.bus,
ptdev->sel.dev, ptdev->sel.func,
orig_addr, ptdev->bar[idx].size,
ptdev->bar[idx].addr);
vm_map_ptdev_mmio(ctx, ptdev->sel.bus,
ptdev->sel.dev, ptdev->sel.func,
dev->bar[idx].addr, ptdev->bar[idx].size,
ptdev->bar[idx].addr);
}
/* bind pin info for pass-through device */
static void
passthru_bind_irq(struct vmctx *ctx, struct pci_vdev *dev)
@ -1767,6 +1800,7 @@ struct pci_vdev_ops passthru = {
.vdev_barwrite = passthru_write,
.vdev_barread = passthru_read,
.vdev_phys_access = passthru_bind_irq,
.vdev_update_bar_map = passthru_update_bar_map,
.vdev_write_dsdt = passthru_write_dsdt,
};
DEFINE_PCI_DEVTYPE(passthru);

View File

@ -64,6 +64,11 @@ struct pci_vdev_ops {
/* ops related to physical resources */
void (*vdev_phys_access)(struct vmctx *ctx, struct pci_vdev *dev);
/* update BAR map callback */
void (*vdev_update_bar_map)(struct vmctx *ctx,
struct pci_vdev *dev, int idx,
uint64_t orig_addr);
/* config space read/write callbacks */
int (*vdev_cfgwrite)(struct vmctx *ctx, int vcpu,
struct pci_vdev *pi, int offset,