summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/cpu/o3/lsq_impl.hh22
-rw-r--r--src/cpu/o3/lsq_unit_impl.hh18
2 files changed, 37 insertions, 3 deletions
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<Impl>::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<Impl>::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<Impl>::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<ReExec*>(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