summaryrefslogtreecommitdiff
path: root/src/cpu/o3
diff options
context:
space:
mode:
authorAli Saidi <Ali.Saidi@ARM.com>2014-01-24 15:29:30 -0600
committerAli Saidi <Ali.Saidi@ARM.com>2014-01-24 15:29:30 -0600
commit6bed6e0352a68723ea55017b3e09a8c279af11ec (patch)
treef7fb2a163ea470144a424bf21a7dd578754546af /src/cpu/o3
parentd3444c6603afe38b00036292a854f52069b90a80 (diff)
downloadgem5-6bed6e0352a68723ea55017b3e09a8c279af11ec.tar.xz
cpu: Add CPU support for generatig wake up events when LLSC adresses are snooped.
This patch add support for generating wake-up events in the CPU when an address that is currently in the exclusive state is hit by a snoop. This mechanism is required for ARMv8 multi-processor support.
Diffstat (limited to 'src/cpu/o3')
-rw-r--r--src/cpu/o3/lsq_unit_impl.hh32
1 files changed, 26 insertions, 6 deletions
diff --git a/src/cpu/o3/lsq_unit_impl.hh b/src/cpu/o3/lsq_unit_impl.hh
index 277fe48d2..7ec59e38d 100644
--- a/src/cpu/o3/lsq_unit_impl.hh
+++ b/src/cpu/o3/lsq_unit_impl.hh
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 2010-2012 ARM Limited
+ * Copyright (c) 2010-2013 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@@ -433,12 +433,13 @@ void
LSQUnit<Impl>::checkSnoop(PacketPtr pkt)
{
int load_idx = loadHead;
+ DPRINTF(LSQUnit, "Got snoop for address %#x\n", pkt->getAddr());
// 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++) {
+ for (int x = 0; x < cpu->numContexts(); x++) {
ThreadContext *tc = cpu->getContext(x);
bool no_squash = cpu->thread[x]->noSquashFromTC;
cpu->thread[x]->noSquashFromTC = true;
@@ -446,13 +447,23 @@ LSQUnit<Impl>::checkSnoop(PacketPtr pkt)
cpu->thread[x]->noSquashFromTC = no_squash;
}
+ Addr invalidate_addr = pkt->getAddr() & cacheBlockMask;
+
+ DynInstPtr ld_inst = loadQueue[load_idx];
+ if (ld_inst) {
+ Addr load_addr = ld_inst->physEffAddr & cacheBlockMask;
+ // Check that this snoop didn't just invalidate our lock flag
+ if (ld_inst->effAddrValid() && load_addr == invalidate_addr &&
+ ld_inst->memReqFlags & Request::LLSC)
+ TheISA::handleLockedSnoopHit(ld_inst.get());
+ }
+
// If this is the only load in the LSQ we don't care
if (load_idx == loadTail)
return;
+
incrLdIdx(load_idx);
- DPRINTF(LSQUnit, "Got snoop for address %#x\n", pkt->getAddr());
- Addr invalidate_addr = pkt->getAddr() & cacheBlockMask;
while (load_idx != loadTail) {
DynInstPtr ld_inst = loadQueue[load_idx];
@@ -468,11 +479,20 @@ LSQUnit<Impl>::checkSnoop(PacketPtr pkt)
if (load_addr == invalidate_addr) {
if (ld_inst->possibleLoadViolation()) {
DPRINTF(LSQUnit, "Conflicting load at addr %#x [sn:%lli]\n",
- ld_inst->physEffAddr, pkt->getAddr(), ld_inst->seqNum);
+ pkt->getAddr(), ld_inst->seqNum);
// Mark the load for re-execution
ld_inst->fault = new ReExec;
} else {
+ DPRINTF(LSQUnit, "HitExternal Snoop for addr %#x [sn:%lli]\n",
+ pkt->getAddr(), ld_inst->seqNum);
+
+ // Make sure that we don't lose a snoop hitting a LOCKED
+ // address since the LOCK* flags don't get updated until
+ // commit.
+ if (ld_inst->memReqFlags & Request::LLSC)
+ TheISA::handleLockedSnoopHit(ld_inst.get());
+
// If a older load checks this and it's true
// then we might have missed the snoop
// in which case we need to invalidate to be sure
@@ -849,7 +869,7 @@ LSQUnit<Impl>::writebackStores()
// misc regs normally updates the result, but this is not
// the desired behavior when handling store conditionals.
inst->recordResult(false);
- bool success = TheISA::handleLockedWrite(inst.get(), req);
+ bool success = TheISA::handleLockedWrite(inst.get(), req, cacheBlockMask);
inst->recordResult(true);
if (!success) {