summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPouya Fotouhi <Pouya.Fotouhi@amd.com>2019-10-22 17:29:57 -0500
committerPouya Fotouhi <pfotouhi@ucdavis.edu>2019-10-30 18:47:09 +0000
commite0040fe8fecbc2642cfc09de54a6a5b52cdf07ec (patch)
treeeadba2a17fa97e37139644ff73ab2bff56d04d08
parentfca416d1545f2833f4412f1750192b91df1f3ef1 (diff)
downloadgem5-e0040fe8fecbc2642cfc09de54a6a5b52cdf07ec.tar.xz
dev: Adding support for large BAR
During PCI setup, this patch checks if a Base Address Register (BAR) is used as a large BAR (64 bits rather than 32), and return proper address range. The order which updates are done is decided by kernel, so this patch implements both cases (writing lower or upper bits first). Bit 2 in a BAR indicates a 64-bit decoder (10X to be more exact, 11X is reserved). The addresses in BARAddrs are full addresses and are set to zero for BAR providing upper 32 bits to avoid conflicts in addr ranges reported. Change-Id: I93303d36ac83dab9ed6837c81e77c9dfb778f409 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/22082 Reviewed-by: Jason Lowe-Power <jason@lowepower.com> Maintainer: Jason Lowe-Power <jason@lowepower.com> Tested-by: kokoro <noreply+kokoro@google.com>
-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?
*/