summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/dev/pci/device.cc27
-rw-r--r--src/dev/pci/device.hh9
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?
*/