diff options
-rw-r--r-- | src/dev/pci/device.cc | 27 | ||||
-rw-r--r-- | src/dev/pci/device.hh | 9 |
2 files changed, 33 insertions, 3 deletions
diff --git a/src/dev/pci/device.cc b/src/dev/pci/device.cc index 1097573f8..e4c4eb170 100644 --- a/src/dev/pci/device.cc +++ b/src/dev/pci/device.cc @@ -380,9 +380,30 @@ PciDevice::writeConfig(PacketPtr pkt) // does it mean something special to write 0 to a BAR? he_new_bar &= ~bar_mask; if (he_new_bar) { - BARAddrs[barnum] = BAR_IO_SPACE(he_old_bar) ? - hostInterface.pioAddr(he_new_bar) : - hostInterface.memAddr(he_new_bar); + if (isLargeBAR(barnum)) { + if (BAR_IO_SPACE(he_old_bar)) + warn("IO BARs can't be set as large BAR"); + uint64_t he_large_bar = + letoh(config.baseAddr[barnum + 1]); + he_large_bar = he_large_bar << 32; + he_large_bar += he_new_bar; + BARAddrs[barnum] = + hostInterface.memAddr(he_large_bar); + } else if (isLargeBAR(barnum - 1)) { + BARAddrs[barnum] = 0; + uint64_t he_large_bar = he_new_bar; + he_large_bar = he_large_bar << 32; + // We need to apply mask to lower bits + he_large_bar += + letoh(config.baseAddr[barnum - 1] + & ~bar_mask); + BARAddrs[barnum - 1] = + hostInterface.memAddr(he_large_bar); + } else { + BARAddrs[barnum] = BAR_IO_SPACE(he_old_bar) ? + hostInterface.pioAddr(he_new_bar) : + hostInterface.memAddr(he_new_bar); + } pioPort.sendRangeChange(); } } diff --git a/src/dev/pci/device.hh b/src/dev/pci/device.hh index ba783a6b1..d1545262e 100644 --- a/src/dev/pci/device.hh +++ b/src/dev/pci/device.hh @@ -116,6 +116,15 @@ class PciDevice : public DmaDevice bool legacyIO[6]; /** + * Does the given BAR represent 32 lower bits of a 64-bit address? + */ + bool + isLargeBAR(int bar) const + { + return bits(config.baseAddr[bar], 2, 1) == 0x2; + } + + /** * Does the given address lie within the space mapped by the given * base address register? */ |