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).
This commit is contained in:
parent
0fcb376e5f
commit
f1ec326be5
1 changed files with 24 additions and 7 deletions
31
src/mem/cache/cache.cc
vendored
31
src/mem/cache/cache.cc
vendored
|
@ -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 {
|
||||
|
|
Loading…
Reference in a new issue