changeset 245cd4691cbf in /z/repo/gem5
details: http://repo.gem5.org/gem5?cmd=changeset;node=245cd4691cbf
description:
        mem: Fix prefetchSquash + memInhibitAsserted bug

        This patch resolves a bug with hardware prefetches. Before a hardware 
prefetch
        is sent towards the memory, the system generates a snoop request to 
check all
        caches above the prefetch generating cache for the presence of the 
prefetth
        target. If the prefetch target is found in the tags or the MSHRs of the 
upper
        caches, the cache sets the prefetchSquashed flag in the snoop packet. 
When the
        snoop packet returns with the prefetchSquashed flag set, the prefetch
        generating cache deallocates the MSHR reserved for the prefetch. If the
        prefetch target is found in the writeback buffer of the upper cache, 
the cache
        sets the memInhibit flag, which signals the prefetch generating cache to
        expect the data from the writeback. When the snoop packet returns with 
the
        memInhibitAsserted flag set, it marks the allocated MSHR as inService 
and
        waits for the data from the writeback.

        If the prefetch target is found in multiple upper level caches, 
specifically
        in the tags or MSHRs of one upper level cache and the writeback buffer 
of
        another, the snoop packet will return with both prefetchSquashed and
        memInhibitAsserted set, while the current code is not written to handle 
such
        an outcome. Current code checks for the prefetchSquashed flag first, if 
it
        finds the flag, it deallocates the reserved MSHR. This leads to assert 
failure
        when the data from the writeback appears at cache. In this fix, we 
simply
        switch the order of checks. We first check for memInhibitAsserted and 
then for
        prefetch squashed.

diffstat:

 src/mem/cache/cache_impl.hh |  38 ++++++++++++++++++++++----------------
 1 files changed, 22 insertions(+), 16 deletions(-)

diffs (55 lines):

diff -r 7f67a8d786a2 -r 245cd4691cbf src/mem/cache/cache_impl.hh
--- a/src/mem/cache/cache_impl.hh       Mon Mar 02 04:00:31 2015 -0500
+++ b/src/mem/cache/cache_impl.hh       Mon Mar 02 04:00:34 2015 -0500
@@ -1966,10 +1966,28 @@
             snoop_pkt.senderState = mshr;
             cpuSidePort->sendTimingSnoopReq(&snoop_pkt);
 
-            // Check to see if the prefetch was squashed by an upper
-            // cache (to prevent us from grabbing the line) or if a
-            // writeback arrived between the time the prefetch was
-            // placed in the MSHRs and when it was selected to be sent.
+            // Check to see if the prefetch was squashed by an upper cache (to
+            // prevent us from grabbing the line) or if a Check to see if a
+            // writeback arrived between the time the prefetch was placed in
+            // the MSHRs and when it was selected to be sent or if the
+            // prefetch was squashed by an upper cache.
+
+            // It is important to check msmInhibitAsserted before
+            // prefetchSquashed. If another cache has asserted MEM_INGIBIT, it
+            // will be sending a response which will arrive at the MSHR
+            // allocated ofr this request. Checking the prefetchSquash first
+            // may result in the MSHR being prematurely deallocated.
+
+            if (snoop_pkt.memInhibitAsserted()) {
+                // If we are getting a non-shared response it is dirty
+                bool pending_dirty_resp = !snoop_pkt.sharedAsserted();
+                markInService(mshr, pending_dirty_resp);
+                DPRINTF(Cache, "Upward snoop of prefetch for addr"
+                        " %#x (%s) hit\n",
+                        tgt_pkt->getAddr(), tgt_pkt->isSecure()? "s": "ns");
+                return NULL;
+            }
+
             if (snoop_pkt.prefetchSquashed() || blk != NULL) {
                 DPRINTF(Cache, "Prefetch squashed by cache.  "
                                "Deallocating mshr target %#x.\n", mshr->addr);
@@ -1983,18 +2001,6 @@
                 return NULL;
             }
 
-            // Check if the prefetch hit a writeback in an upper cache
-            // and if so we will eventually get a HardPFResp from
-            // above
-            if (snoop_pkt.memInhibitAsserted()) {
-                // If we are getting a non-shared response it is dirty
-                bool pending_dirty_resp = !snoop_pkt.sharedAsserted();
-                markInService(mshr, pending_dirty_resp);
-                DPRINTF(Cache, "Upward snoop of prefetch for addr"
-                        " %#x (%s) hit\n",
-                        tgt_pkt->getAddr(), tgt_pkt->isSecure()? "s": "ns");
-                return NULL;
-            }
         }
 
         pkt = getBusPacket(tgt_pkt, blk, mshr->needsExclusive());
_______________________________________________
gem5-dev mailing list
[email protected]
http://m5sim.org/mailman/listinfo/gem5-dev

Reply via email to