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);
|
||||
}
|
||||
|
||||
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? */
|
||||
static int
|
||||
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? */
|
||||
if (changed & PCIM_CMD_PORTEN) {
|
||||
if (porten(dev))
|
||||
enable_bar(dev, i);
|
||||
register_bar(dev, i);
|
||||
else
|
||||
disable_bar(dev, i);
|
||||
unregister_bar(dev, i);
|
||||
}
|
||||
break;
|
||||
case PCIBAR_MEM32:
|
||||
|
@ -2033,10 +1973,10 @@ pci_emul_cmdsts_write(struct pci_vdev *dev, int coff, uint32_t new, int bytes)
|
|||
/* MMIO address space decoding changed? */
|
||||
if (changed & PCIM_CMD_MEMEN) {
|
||||
if (memen(dev))
|
||||
enable_bar(dev, i);
|
||||
register_bar(dev, i);
|
||||
else
|
||||
disable_bar(dev, i);
|
||||
}
|
||||
unregister_bar(dev, i);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
|
|
Loading…
Reference in New Issue