mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-06-25 06:51:49 +00:00
dm: register_bar/unregister_bar when bar enable/disable
Sometimes guest OS writes PCIR_COMMAND register to disable the device, then update the bar address followed by a write to PCIR_COMMAND register to enable the device again. In this case unregister_bar/register_bar should be called otherwise the IO/MMIO regions monitored by device model will not be updated accordingly. Tracked-On: #2962 Signed-off-by: Yu Wang <yu1.wang@intel.com> Signed-off-by: Jian Jun Chen <jian.jun.chen@intel.com> Signed-off-by: Liu Shuo A <shuo.a.liu@intel.com> Acked-by: Yin Fengwei <fengwei.yin@intel.com>
This commit is contained in:
parent
b838e9b720
commit
d648df766c
@ -541,66 +541,6 @@ register_bar(struct pci_vdev *dev, int idx)
|
|||||||
modify_bar_registration(dev, idx, 1);
|
modify_bar_registration(dev, idx, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
enable_bar(struct pci_vdev *dev, int idx)
|
|
||||||
{
|
|
||||||
int error = 0;
|
|
||||||
struct inout_port iop;
|
|
||||||
struct mem_range mr;
|
|
||||||
|
|
||||||
switch (dev->bar[idx].type) {
|
|
||||||
case PCIBAR_IO:
|
|
||||||
bzero(&iop, sizeof(struct inout_port));
|
|
||||||
iop.name = dev->name;
|
|
||||||
iop.port = dev->bar[idx].addr;
|
|
||||||
iop.size = dev->bar[idx].size;
|
|
||||||
error = enable_inout(&iop);
|
|
||||||
break;
|
|
||||||
case PCIBAR_MEM32:
|
|
||||||
case PCIBAR_MEM64:
|
|
||||||
bzero(&mr, sizeof(struct mem_range));
|
|
||||||
mr.name = dev->name;
|
|
||||||
mr.base = dev->bar[idx].addr;
|
|
||||||
mr.size = dev->bar[idx].size;
|
|
||||||
error = enable_mem(&mr);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
error = EINVAL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
assert(error == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
disable_bar(struct pci_vdev *dev, int idx)
|
|
||||||
{
|
|
||||||
int error = 0;
|
|
||||||
struct inout_port iop;
|
|
||||||
struct mem_range mr;
|
|
||||||
|
|
||||||
switch (dev->bar[idx].type) {
|
|
||||||
case PCIBAR_IO:
|
|
||||||
bzero(&iop, sizeof(struct inout_port));
|
|
||||||
iop.name = dev->name;
|
|
||||||
iop.port = dev->bar[idx].addr;
|
|
||||||
iop.size = dev->bar[idx].size;
|
|
||||||
error = disable_inout(&iop);
|
|
||||||
break;
|
|
||||||
case PCIBAR_MEM32:
|
|
||||||
case PCIBAR_MEM64:
|
|
||||||
bzero(&mr, sizeof(struct mem_range));
|
|
||||||
mr.name = dev->name;
|
|
||||||
mr.base = dev->bar[idx].addr;
|
|
||||||
mr.size = dev->bar[idx].size;
|
|
||||||
error = disable_mem(&mr);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
error = EINVAL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
assert(error == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Are we decoding i/o port accesses for the emulated pci device? */
|
/* Are we decoding i/o port accesses for the emulated pci device? */
|
||||||
static int
|
static int
|
||||||
porten(struct pci_vdev *dev)
|
porten(struct pci_vdev *dev)
|
||||||
@ -2023,9 +1963,9 @@ pci_emul_cmdsts_write(struct pci_vdev *dev, int coff, uint32_t new, int bytes)
|
|||||||
/* I/O address space decoding changed? */
|
/* I/O address space decoding changed? */
|
||||||
if (changed & PCIM_CMD_PORTEN) {
|
if (changed & PCIM_CMD_PORTEN) {
|
||||||
if (porten(dev))
|
if (porten(dev))
|
||||||
enable_bar(dev, i);
|
register_bar(dev, i);
|
||||||
else
|
else
|
||||||
disable_bar(dev, i);
|
unregister_bar(dev, i);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case PCIBAR_MEM32:
|
case PCIBAR_MEM32:
|
||||||
@ -2033,9 +1973,9 @@ pci_emul_cmdsts_write(struct pci_vdev *dev, int coff, uint32_t new, int bytes)
|
|||||||
/* MMIO address space decoding changed? */
|
/* MMIO address space decoding changed? */
|
||||||
if (changed & PCIM_CMD_MEMEN) {
|
if (changed & PCIM_CMD_MEMEN) {
|
||||||
if (memen(dev))
|
if (memen(dev))
|
||||||
enable_bar(dev, i);
|
register_bar(dev, i);
|
||||||
else
|
else
|
||||||
disable_bar(dev, i);
|
unregister_bar(dev, i);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
Loading…
Reference in New Issue
Block a user