summaryrefslogtreecommitdiff
path: root/src/mem/cache
diff options
context:
space:
mode:
authorAndreas Hansson <andreas.hansson@arm.com>2015-12-31 09:33:25 -0500
committerAndreas Hansson <andreas.hansson@arm.com>2015-12-31 09:33:25 -0500
commitf1ec326be59b137ff0955b4d80e6516754016fd5 (patch)
treeeb538d2694bbf9b2cae82ab0ea88893cd301463d /src/mem/cache
parent0fcb376e5fc6bc0a7b16dc4595d4a7e3f910cbc8 (diff)
downloadgem5-f1ec326be59b137ff0955b4d80e6516754016fd5.tar.xz
mem: Do not alter cache block state on uncacheable snoops
This patch ensures we do not respond with a Modified (dirty and writable) line if the request is uncacheable, and that the cache responding retains the line without modifying the state (even if responding).
Diffstat (limited to 'src/mem/cache')
-rw-r--r--src/mem/cache/cache.cc31
1 files changed, 24 insertions, 7 deletions
diff --git a/src/mem/cache/cache.cc b/src/mem/cache/cache.cc
index ecdf4c855..991463d76 100644
--- a/src/mem/cache/cache.cc
+++ b/src/mem/cache/cache.cc
@@ -1904,6 +1904,13 @@ Cache::handleSnoop(PacketPtr pkt, CacheBlk *blk, bool is_timing,
bool invalidate = pkt->isInvalidate();
bool M5_VAR_USED needs_writable = pkt->needsWritable();
+ // at the moment we could get an uncacheable write which does not
+ // have the invalidate flag, and we need a suitable way of dealing
+ // with this case
+ panic_if(invalidate && pkt->req->isUncacheable(),
+ "%s got an invalidating uncacheable snoop request %s to %#llx",
+ name(), pkt->cmdString(), pkt->getAddr());
+
uint32_t snoop_delay = 0;
if (forwardSnoops) {
@@ -1988,15 +1995,18 @@ Cache::handleSnoop(PacketPtr pkt, CacheBlk *blk, bool is_timing,
return snoop_delay;
}
- if (!pkt->req->isUncacheable() && pkt->isRead() && !invalidate) {
- // reading without requiring the line in a writable state,
- // note that we retain the block as Owned if it is Modified
- // (dirty data), with the response taken care of below, and
- // otherwhise simply downgrade from Exclusive to Shared (or
- // remain in Shared)
+ if (pkt->isRead() && !invalidate) {
+ // reading without requiring the line in a writable state
assert(!needs_writable);
pkt->setHasSharers();
- blk->status &= ~BlkWritable;
+
+ // if the requesting packet is uncacheable, retain the line in
+ // the current state, otherwhise unset the writable flag,
+ // which means we go from Modified to Owned (and will respond
+ // below), remain in Owned (and will respond below), from
+ // Exclusive to Shared, or remain in Shared
+ if (!pkt->req->isUncacheable())
+ blk->status &= ~BlkWritable;
}
if (respond) {
@@ -2020,6 +2030,13 @@ Cache::handleSnoop(PacketPtr pkt, CacheBlk *blk, bool is_timing,
// we already called setHasSharers above
}
+ // if we are returning a writable and dirty (Modified) line,
+ // we should be invalidating the line
+ panic_if(!invalidate && !pkt->hasSharers(),
+ "%s is passing a Modified line through %s to %#llx, "
+ "but keeping the block",
+ name(), pkt->cmdString(), pkt->getAddr());
+
if (is_timing) {
doTimingSupplyResponse(pkt, blk->data, is_deferred, pending_inval);
} else {