diff --git a/src/cpu/o3/lsq_impl.hh b/src/cpu/o3/lsq_impl.hh index 2c9c6eb82..e0107e36a 100644 --- a/src/cpu/o3/lsq_impl.hh +++ b/src/cpu/o3/lsq_impl.hh @@ -346,7 +346,29 @@ LSQ::recvTimingResp(PacketPtr pkt) if (pkt->isError()) DPRINTF(LSQ, "Got error packet back for address: %#X\n", pkt->getAddr()); + thread[pkt->req->threadId()].completeDataAccess(pkt); + + if (pkt->isInvalidate()) { + // This response also contains an invalidate; e.g. this can be the case + // if cmd is ReadRespWithInvalidate. + // + // The calling order between completeDataAccess and checkSnoop matters. + // By calling checkSnoop after completeDataAccess, we ensure that the + // fault set by checkSnoop is not lost. Calling writeback (more + // specifically inst->completeAcc) in completeDataAccess overwrites + // fault, and in case this instruction requires squashing (as + // determined by checkSnoop), the ReExec fault set by checkSnoop would + // be lost otherwise. + + DPRINTF(LSQ, "received invalidation with response for addr:%#x\n", + pkt->getAddr()); + + for (ThreadID tid = 0; tid < numThreads; tid++) { + thread[tid].checkSnoop(pkt); + } + } + delete pkt->req; delete pkt; return true; diff --git a/src/cpu/o3/lsq_unit_impl.hh b/src/cpu/o3/lsq_unit_impl.hh index 0cc412811..9c500443e 100644 --- a/src/cpu/o3/lsq_unit_impl.hh +++ b/src/cpu/o3/lsq_unit_impl.hh @@ -562,7 +562,7 @@ LSQUnit::checkViolations(int load_idx, DynInstPtr &inst) // Otherwise, mark the load has a possible load violation // and if we see a snoop before it's commited, we need to squash ld_inst->possibleLoadViolation(true); - DPRINTF(LSQUnit, "Found possible load violaiton at addr: %#x" + DPRINTF(LSQUnit, "Found possible load violation at addr: %#x" " between instructions [sn:%lli] and [sn:%lli]\n", inst_eff_addr1, inst->seqNum, ld_inst->seqNum); } else { @@ -1124,8 +1124,20 @@ LSQUnit::writeback(DynInstPtr &inst, PacketPtr pkt) if (!inst->isExecuted()) { inst->setExecuted(); - // Complete access to copy data to proper place. - inst->completeAcc(pkt); + if (inst->fault == NoFault) { + // Complete access to copy data to proper place. + inst->completeAcc(pkt); + } else { + // If the instruction has an outstanding fault, we cannot complete + // the access as this discards the current fault. + + // If we have an outstanding fault, the fault should only be of + // type ReExec. + assert(dynamic_cast(inst->fault.get()) != nullptr); + + DPRINTF(LSQUnit, "Not completing instruction [sn:%lli] access " + "due to pending fault.\n", inst->seqNum); + } } // Need to insert instruction into queue to commit