summaryrefslogtreecommitdiff
path: root/src/cpu
diff options
context:
space:
mode:
authorAli Saidi <Ali.Saidi@ARM.com>2013-01-07 13:05:33 -0500
committerAli Saidi <Ali.Saidi@ARM.com>2013-01-07 13:05:33 -0500
commit69d419f31383ac7801e1debb62d5bbf7cb899e3c (patch)
tree8081815bc613db0126c785f0b14a6ade6a651ad1 /src/cpu
parent5146a69835bc9ba37fba7d3b0ff72ecaf9b98b74 (diff)
downloadgem5-69d419f31383ac7801e1debb62d5bbf7cb899e3c.tar.xz
o3: Fix issue with LLSC ordering and speculation
This patch unlocks the cpu-local monitor when the CPU sees a snoop to a locked address. Previously we relied on the cache to handle the locking for us, however some users on the gem5 mailing list reported a case where the cpu speculatively executes a ll operation after a pending sc operation in the pipeline and that makes the cache monitor valid. This should handle that case by invaliding the local monitor.
Diffstat (limited to 'src/cpu')
-rw-r--r--src/cpu/o3/lsq_unit_impl.hh14
1 files changed, 13 insertions, 1 deletions
diff --git a/src/cpu/o3/lsq_unit_impl.hh b/src/cpu/o3/lsq_unit_impl.hh
index 8e12e990b..799759557 100644
--- a/src/cpu/o3/lsq_unit_impl.hh
+++ b/src/cpu/o3/lsq_unit_impl.hh
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010-2011 ARM Limited
+ * Copyright (c) 2010-2012 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@@ -435,6 +435,18 @@ LSQUnit<Impl>::checkSnoop(PacketPtr pkt)
cacheBlockMask = ~(bs - 1);
}
+ // Unlock the cpu-local monitor when the CPU sees a snoop to a locked
+ // address. The CPU can speculatively execute a LL operation after a pending
+ // SC operation in the pipeline and that can make the cache monitor the CPU
+ // is connected to valid while it really shouldn't be.
+ for (int x = 0; x < cpu->numActiveThreads(); x++) {
+ ThreadContext *tc = cpu->getContext(x);
+ bool no_squash = cpu->thread[x]->noSquashFromTC;
+ cpu->thread[x]->noSquashFromTC = true;
+ TheISA::handleLockedSnoop(tc, pkt, cacheBlockMask);
+ cpu->thread[x]->noSquashFromTC = no_squash;
+ }
+
// If this is the only load in the LSQ we don't care
if (load_idx == loadTail)
return;