mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2026-06-07 09:41:30 +00:00
dm: fix the issue when guest tries to disable memory range access
According to PCI spec 3.0 section 6.2.2 "Device Control", guest
could write the command register to control device response to
io/mem access.
The origial code register/unregister the memory range which is
not suitable because it can't handle the sequence:
1. disble the device response to specific memory range
2. reboot guest (DM will try to free the memory range which
was freed in step 1 already)
Tracked-On: #1277
Signed-off-by: Yin Fengwei <fengwei.yin@intel.com>
Acked-by: Yu Wang <yu1.wang@intel.com>
This commit is contained in:
@@ -508,6 +508,66 @@ 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)
|
||||
@@ -1875,9 +1935,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))
|
||||
register_bar(dev, i);
|
||||
enable_bar(dev, i);
|
||||
else
|
||||
unregister_bar(dev, i);
|
||||
disable_bar(dev, i);
|
||||
}
|
||||
break;
|
||||
case PCIBAR_MEM32:
|
||||
@@ -1885,9 +1945,9 @@ 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))
|
||||
register_bar(dev, i);
|
||||
enable_bar(dev, i);
|
||||
else
|
||||
unregister_bar(dev, i);
|
||||
disable_bar(dev, i);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
||||
Reference in New Issue
Block a user