From: Ali Saidi Date: Fri, 15 Jul 2011 16:53:35 +0000 (-0500) Subject: Mem: Fix issue with prefetches originating at non-L1 caches getting stale data X-Git-Tag: stable_2012_02_02~162 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=147095cb0886a962620e60b6950a68931fbd734a;p=gem5.git 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. --- 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::timingAccess(PacketPtr pkt) // must be cache-to-cache response from upper to lower level ForwardResponseRecord *rec = dynamic_cast(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::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);