diff options
author | Ali Saidi <Ali.Saidi@ARM.com> | 2011-07-15 11:53:35 -0500 |
---|---|---|
committer | Ali Saidi <Ali.Saidi@ARM.com> | 2011-07-15 11:53:35 -0500 |
commit | 147095cb0886a962620e60b6950a68931fbd734a (patch) | |
tree | b81211a4e2441c897149b4823506a60f49966a79 /src/mem/cache/cache_impl.hh | |
parent | 69ef57fd0f226af90faf46ac877343b5493df693 (diff) | |
download | gem5-147095cb0886a962620e60b6950a68931fbd734a.tar.xz |
Mem: Fix issue with prefetches originating at non-L1 caches getting stale data
Prefetch requests issued from the L2 or below wouldn't check if valid data is
present higher in the system. If a prefetch into the L2 occured at the same
time as writeback from a higher-level cache the dirty data could be replaced
in by unmodified data in memory.
Diffstat (limited to 'src/mem/cache/cache_impl.hh')
-rw-r--r-- | src/mem/cache/cache_impl.hh | 39 |
1 files changed, 38 insertions, 1 deletions
diff --git a/src/mem/cache/cache_impl.hh b/src/mem/cache/cache_impl.hh index d4a969d9b..e1aed8b0c 100644 --- a/src/mem/cache/cache_impl.hh +++ b/src/mem/cache/cache_impl.hh @@ -420,7 +420,17 @@ Cache<TagStore>::timingAccess(PacketPtr pkt) // must be cache-to-cache response from upper to lower level ForwardResponseRecord *rec = dynamic_cast<ForwardResponseRecord *>(pkt->senderState); - assert(rec != NULL); + + if (rec == NULL) { + assert(pkt->cmd == MemCmd::HardPFResp); + // Check if it's a prefetch response and handle it. We shouldn't + // get any other kinds of responses without FRRs. + DPRINTF(Cache, "Got prefetch response from above for addr %#x\n", + pkt->getAddr()); + handleResponse(pkt); + return true; + } + rec->restore(pkt, this); delete rec; memSidePort->respond(pkt, time); @@ -1472,6 +1482,33 @@ Cache<TagStore>::getTimingPacket() pkt = tgt_pkt; } else { BlkType *blk = tags->findBlock(mshr->addr); + + if (tgt_pkt->cmd == MemCmd::HardPFReq) { + // It might be possible for a writeback to arrive between + // the time the prefetch is placed in the MSHRs and when + // it's selected to send... if so, this assert will catch + // that, and then we'll have to figure out what to do. + assert(blk == NULL); + + // We need to check the caches above us to verify that they don't have + // a copy of this block in the dirty state at the moment. Without this + // check we could get a stale copy from memory that might get used + // in place of the dirty one. + PacketPtr snoop_pkt = new Packet(tgt_pkt, true); + snoop_pkt->setExpressSnoop(); + snoop_pkt->senderState = mshr; + cpuSidePort->sendTiming(snoop_pkt); + + if (snoop_pkt->memInhibitAsserted()) { + markInService(mshr, snoop_pkt); + DPRINTF(Cache, "Upward snoop of prefetch for addr %#x hit\n", + tgt_pkt->getAddr()); + delete snoop_pkt; + return NULL; + } + delete snoop_pkt; + } + pkt = getBusPacket(tgt_pkt, blk, mshr->needsExclusive()); mshr->isForward = (pkt == NULL); |