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:
parent
cee2f8b288
commit
811d1fe93d
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue