diff -r 5516ad2c3618 -r a88d12956581 src/mem/cache/cache_impl.hh --- a/src/mem/cache/cache_impl.hh Wed Jul 13 16:42:43 2011 -0500 +++ b/src/mem/cache/cache_impl.hh Wed Jul 13 16:42:43 2011 -0500 @@ -420,6 +420,17 @@ // must be cache-to-cache response from upper to lower level ForwardResponseRecord *rec = dynamic_cast(pkt->senderState); + + 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; + } + assert(rec != NULL); rec->restore(pkt, this); delete rec; @@ -1472,6 +1483,35 @@ 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 copy from a lower level or main memory that + // isn't dirty and it might replace a dirty one in cache if the upper + // level happens to write back in the middle of a prefetch. If they do + // the cache will supply the data. + 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);