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.
This commit is contained in:
parent
69ef57fd0f
commit
147095cb08
1 changed files with 38 additions and 1 deletions
39
src/mem/cache/cache_impl.hh
vendored
39
src/mem/cache/cache_impl.hh
vendored
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue