misc: Revert "arch,cpu,mem,sim: Fold arch/locked_mem.hh..."
This reverts commit a3f85217ab,
https://gem5-review.googlesource.com/c/public/gem5/+/48384
The reason for reverting this commit is it causes the Nightly build to
timeout: https://www.mail-archive.com/gem5-dev@gem5.org/msg40344.html
The exact cause of this failure was a stalling with the O3 processor on
ARM. The simulation reaches the following error and repeats until
timeout:
```
build/ARM/arch/arm/isa.cc:2634: warn: context 0: 2136500000 consecutive store conditional failures
```
The "realview-o3-ARM-x86_64-opt" test can replicate this:
```
./main.py run -j8 --uid
SuiteUID:tests/gem5/fs/linux/arm/test.py:realview-o3-ARM-x86_64-opt
```
Change-Id: I9e9a20753c2a25c143e6a73f58716feb41861cde
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/49927
Maintainer: Bobby R. Bruce <bbruce@ucdavis.edu>
Maintainer: Giacomo Travaglini <giacomo.travaglini@arm.com>
Reviewed-by: Giacomo Travaglini <giacomo.travaglini@arm.com>
Reviewed-by: Gabe Black <gabe.black@gmail.com>
Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
committed by
Jason Lowe-Power
parent
737cdd7397
commit
1853d57dc3
@@ -59,6 +59,7 @@ env.SwitchingHeaders(
|
||||
Split('''
|
||||
decoder.hh
|
||||
isa.hh
|
||||
locked_mem.hh
|
||||
page_size.hh
|
||||
pcstate.hh
|
||||
vecregs.hh
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#include "arch/arm/faults.hh"
|
||||
#include "arch/arm/htm.hh"
|
||||
#include "arch/arm/insts/tme64.hh"
|
||||
#include "arch/arm/locked_mem.hh"
|
||||
#include "arch/generic/memhelpers.hh"
|
||||
#include "debug/ArmTme.hh"
|
||||
#include "mem/packet_access.hh"
|
||||
@@ -119,7 +120,7 @@ Tstart64::completeAcc(PacketPtr pkt, ExecContext *xc,
|
||||
armcpt->save(tc);
|
||||
armcpt->destinationRegister(dest);
|
||||
|
||||
tc->getIsaPtr()->globalClearExclusive();
|
||||
ArmISA::globalClearExclusive(tc);
|
||||
}
|
||||
|
||||
xc->setIntRegOperand(this, 0, (Dest64) & mask(intWidth));
|
||||
@@ -261,7 +262,7 @@ MicroTcommit64::completeAcc(PacketPtr pkt, ExecContext *xc,
|
||||
assert(tme_checkpoint->valid());
|
||||
|
||||
tme_checkpoint->reset();
|
||||
tc->getIsaPtr()->globalClearExclusive();
|
||||
ArmISA::globalClearExclusive(tc);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -42,17 +42,14 @@
|
||||
#include "arch/arm/interrupts.hh"
|
||||
#include "arch/arm/mmu.hh"
|
||||
#include "arch/arm/pmu.hh"
|
||||
#include "arch/arm/regs/misc.hh"
|
||||
#include "arch/arm/self_debug.hh"
|
||||
#include "arch/arm/system.hh"
|
||||
#include "arch/arm/tlbi_op.hh"
|
||||
#include "arch/arm/utility.hh"
|
||||
#include "base/cprintf.hh"
|
||||
#include "cpu/base.hh"
|
||||
#include "cpu/checker/cpu.hh"
|
||||
#include "cpu/reg_class.hh"
|
||||
#include "debug/Arm.hh"
|
||||
#include "debug/LLSC.hh"
|
||||
#include "debug/MiscRegs.hh"
|
||||
#include "dev/arm/generic_timer.hh"
|
||||
#include "dev/arm/gic_v3.hh"
|
||||
@@ -2558,103 +2555,5 @@ ISA::MiscRegLUTEntryInitializer::highest(ArmSystem *const sys) const
|
||||
return *this;
|
||||
}
|
||||
|
||||
void
|
||||
ISA::handleLockedSnoop(PacketPtr pkt, Addr cacheBlockMask)
|
||||
{
|
||||
// Should only every see invalidations / direct writes
|
||||
assert(pkt->isInvalidate() || pkt->isWrite());
|
||||
|
||||
DPRINTF(LLSC, "%s: handling snoop for address: %#x locked: %d\n",
|
||||
tc->getCpuPtr()->name(), pkt->getAddr(),
|
||||
tc->readMiscReg(MISCREG_LOCKFLAG));
|
||||
if (!tc->readMiscReg(MISCREG_LOCKFLAG))
|
||||
return;
|
||||
|
||||
Addr locked_addr = tc->readMiscReg(MISCREG_LOCKADDR) & cacheBlockMask;
|
||||
// If no caches are attached, the snoop address always needs to be masked
|
||||
Addr snoop_addr = pkt->getAddr() & cacheBlockMask;
|
||||
|
||||
DPRINTF(LLSC, "%s: handling snoop for address: %#x locked addr: %#x\n",
|
||||
tc->getCpuPtr()->name(), snoop_addr, locked_addr);
|
||||
if (locked_addr == snoop_addr) {
|
||||
DPRINTF(LLSC, "%s: address match, clearing lock and signaling sev\n",
|
||||
tc->getCpuPtr()->name());
|
||||
tc->setMiscReg(MISCREG_LOCKFLAG, false);
|
||||
// Implement ARMv8 WFE/SEV semantics
|
||||
sendEvent(tc);
|
||||
tc->setMiscReg(MISCREG_SEV_MAILBOX, true);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ISA::handleLockedRead(const RequestPtr &req)
|
||||
{
|
||||
tc->setMiscReg(MISCREG_LOCKADDR, req->getPaddr());
|
||||
tc->setMiscReg(MISCREG_LOCKFLAG, true);
|
||||
DPRINTF(LLSC, "%s: Placing address %#x in monitor\n",
|
||||
tc->getCpuPtr()->name(), req->getPaddr());
|
||||
}
|
||||
|
||||
void
|
||||
ISA::handleLockedSnoopHit()
|
||||
{
|
||||
DPRINTF(LLSC, "%s: handling snoop lock hit address: %#x\n",
|
||||
tc->getCpuPtr()->name(), tc->readMiscReg(MISCREG_LOCKADDR));
|
||||
tc->setMiscReg(MISCREG_LOCKFLAG, false);
|
||||
tc->setMiscReg(MISCREG_SEV_MAILBOX, true);
|
||||
}
|
||||
|
||||
bool
|
||||
ISA::handleLockedWrite(const RequestPtr &req, Addr cacheBlockMask)
|
||||
{
|
||||
if (req->isSwap())
|
||||
return true;
|
||||
|
||||
DPRINTF(LLSC, "%s: handling locked write for address %#x in monitor\n",
|
||||
tc->getCpuPtr()->name(), req->getPaddr());
|
||||
// Verify that the lock flag is still set and the address
|
||||
// is correct
|
||||
bool lock_flag = tc->readMiscReg(MISCREG_LOCKFLAG);
|
||||
Addr lock_addr = tc->readMiscReg(MISCREG_LOCKADDR) & cacheBlockMask;
|
||||
if (!lock_flag || (req->getPaddr() & cacheBlockMask) != lock_addr) {
|
||||
// Lock flag not set or addr mismatch in CPU;
|
||||
// don't even bother sending to memory system
|
||||
req->setExtraData(0);
|
||||
tc->setMiscReg(MISCREG_LOCKFLAG, false);
|
||||
DPRINTF(LLSC, "%s: clearing lock flag in handle locked write\n",
|
||||
tc->getCpuPtr()->name());
|
||||
// the rest of this code is not architectural;
|
||||
// it's just a debugging aid to help detect
|
||||
// livelock by warning on long sequences of failed
|
||||
// store conditionals
|
||||
int stCondFailures = tc->readStCondFailures();
|
||||
stCondFailures++;
|
||||
tc->setStCondFailures(stCondFailures);
|
||||
if (stCondFailures % 100000 == 0) {
|
||||
warn("context %d: %d consecutive "
|
||||
"store conditional failures\n",
|
||||
tc->contextId(), stCondFailures);
|
||||
}
|
||||
|
||||
// store conditional failed already, so don't issue it to mem
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
ISA::globalClearExclusive()
|
||||
{
|
||||
// A spinlock would typically include a Wait For Event (WFE) to
|
||||
// conserve energy. The ARMv8 architecture specifies that an event
|
||||
// is automatically generated when clearing the exclusive monitor
|
||||
// to wake up the processor in WFE.
|
||||
DPRINTF(LLSC, "Clearing lock and signaling sev\n");
|
||||
tc->setMiscReg(MISCREG_LOCKFLAG, false);
|
||||
// Implement ARMv8 WFE/SEV semantics
|
||||
sendEvent(tc);
|
||||
tc->setMiscReg(MISCREG_SEV_MAILBOX, true);
|
||||
}
|
||||
|
||||
} // namespace ArmISA
|
||||
} // namespace gem5
|
||||
|
||||
@@ -919,16 +919,6 @@ namespace ArmISA
|
||||
}
|
||||
|
||||
void copyRegsFrom(ThreadContext *src) override;
|
||||
|
||||
void handleLockedRead(const RequestPtr &req) override;
|
||||
|
||||
bool handleLockedWrite(const RequestPtr &req,
|
||||
Addr cacheBlockMask) override;
|
||||
|
||||
void handleLockedSnoop(PacketPtr pkt, Addr cacheBlockMask) override;
|
||||
void handleLockedSnoopHit() override;
|
||||
|
||||
void globalClearExclusive() override;
|
||||
};
|
||||
|
||||
} // namespace ArmISA
|
||||
|
||||
168
src/arch/arm/locked_mem.hh
Normal file
168
src/arch/arm/locked_mem.hh
Normal file
@@ -0,0 +1,168 @@
|
||||
/*
|
||||
* Copyright (c) 2012-2013,2017, 2020 ARM Limited
|
||||
* All rights reserved
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
* not be construed as granting a license to any other intellectual
|
||||
* property including but not limited to intellectual property relating
|
||||
* to a hardware implementation of the functionality of the software
|
||||
* licensed hereunder. You may use the software subject to the license
|
||||
* terms below provided that you ensure that this notice is replicated
|
||||
* unmodified and in its entirety in all distributions of the software,
|
||||
* modified or unmodified, in source code or in binary form.
|
||||
*
|
||||
* Copyright (c) 2006 The Regents of The University of Michigan
|
||||
* Copyright (c) 2007-2008 The Florida State University
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met: redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer;
|
||||
* redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution;
|
||||
* neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef __ARCH_ARM_LOCKED_MEM_HH__
|
||||
#define __ARCH_ARM_LOCKED_MEM_HH__
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* ISA-specific helper functions for locked memory accesses.
|
||||
*/
|
||||
|
||||
#include "arch/arm/regs/misc.hh"
|
||||
#include "arch/arm/utility.hh"
|
||||
#include "debug/LLSC.hh"
|
||||
#include "mem/packet.hh"
|
||||
#include "mem/request.hh"
|
||||
|
||||
namespace gem5
|
||||
{
|
||||
|
||||
namespace ArmISA
|
||||
{
|
||||
template <class XC>
|
||||
inline void
|
||||
handleLockedSnoop(XC *xc, PacketPtr pkt, Addr cacheBlockMask)
|
||||
{
|
||||
// Should only every see invalidations / direct writes
|
||||
assert(pkt->isInvalidate() || pkt->isWrite());
|
||||
|
||||
DPRINTF(LLSC,"%s: handling snoop for address: %#x locked: %d\n",
|
||||
xc->getCpuPtr()->name(),pkt->getAddr(),
|
||||
xc->readMiscReg(MISCREG_LOCKFLAG));
|
||||
if (!xc->readMiscReg(MISCREG_LOCKFLAG))
|
||||
return;
|
||||
|
||||
Addr locked_addr = xc->readMiscReg(MISCREG_LOCKADDR) & cacheBlockMask;
|
||||
// If no caches are attached, the snoop address always needs to be masked
|
||||
Addr snoop_addr = pkt->getAddr() & cacheBlockMask;
|
||||
|
||||
DPRINTF(LLSC,"%s: handling snoop for address: %#x locked addr: %#x\n",
|
||||
xc->getCpuPtr()->name(),snoop_addr, locked_addr);
|
||||
if (locked_addr == snoop_addr) {
|
||||
DPRINTF(LLSC,"%s: address match, clearing lock and signaling sev\n",
|
||||
xc->getCpuPtr()->name());
|
||||
xc->setMiscReg(MISCREG_LOCKFLAG, false);
|
||||
// Implement ARMv8 WFE/SEV semantics
|
||||
sendEvent(xc);
|
||||
xc->setMiscReg(MISCREG_SEV_MAILBOX, true);
|
||||
}
|
||||
}
|
||||
|
||||
template <class XC>
|
||||
inline void
|
||||
handleLockedRead(XC *xc, const RequestPtr &req)
|
||||
{
|
||||
xc->setMiscReg(MISCREG_LOCKADDR, req->getPaddr());
|
||||
xc->setMiscReg(MISCREG_LOCKFLAG, true);
|
||||
DPRINTF(LLSC,"%s: Placing address %#x in monitor\n", xc->getCpuPtr()->name(),
|
||||
req->getPaddr());
|
||||
}
|
||||
|
||||
template <class XC>
|
||||
inline void
|
||||
handleLockedSnoopHit(XC *xc)
|
||||
{
|
||||
DPRINTF(LLSC,"%s: handling snoop lock hit address: %#x\n",
|
||||
xc->getCpuPtr()->name(), xc->readMiscReg(MISCREG_LOCKADDR));
|
||||
xc->setMiscReg(MISCREG_LOCKFLAG, false);
|
||||
xc->setMiscReg(MISCREG_SEV_MAILBOX, true);
|
||||
}
|
||||
|
||||
template <class XC>
|
||||
inline bool
|
||||
handleLockedWrite(XC *xc, const RequestPtr &req, Addr cacheBlockMask)
|
||||
{
|
||||
if (req->isSwap())
|
||||
return true;
|
||||
|
||||
DPRINTF(LLSC,"%s: handling locked write for address %#x in monitor\n",
|
||||
xc->getCpuPtr()->name(), req->getPaddr());
|
||||
// Verify that the lock flag is still set and the address
|
||||
// is correct
|
||||
bool lock_flag = xc->readMiscReg(MISCREG_LOCKFLAG);
|
||||
Addr lock_addr = xc->readMiscReg(MISCREG_LOCKADDR) & cacheBlockMask;
|
||||
if (!lock_flag || (req->getPaddr() & cacheBlockMask) != lock_addr) {
|
||||
// Lock flag not set or addr mismatch in CPU;
|
||||
// don't even bother sending to memory system
|
||||
req->setExtraData(0);
|
||||
xc->setMiscReg(MISCREG_LOCKFLAG, false);
|
||||
DPRINTF(LLSC,"%s: clearing lock flag in handle locked write\n",
|
||||
xc->getCpuPtr()->name());
|
||||
// the rest of this code is not architectural;
|
||||
// it's just a debugging aid to help detect
|
||||
// livelock by warning on long sequences of failed
|
||||
// store conditionals
|
||||
int stCondFailures = xc->readStCondFailures();
|
||||
stCondFailures++;
|
||||
xc->setStCondFailures(stCondFailures);
|
||||
if (stCondFailures % 100000 == 0) {
|
||||
warn("context %d: %d consecutive "
|
||||
"store conditional failures\n",
|
||||
xc->contextId(), stCondFailures);
|
||||
}
|
||||
|
||||
// store conditional failed already, so don't issue it to mem
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class XC>
|
||||
inline void
|
||||
globalClearExclusive(XC *xc)
|
||||
{
|
||||
// A spinlock would typically include a Wait For Event (WFE) to
|
||||
// conserve energy. The ARMv8 architecture specifies that an event
|
||||
// is automatically generated when clearing the exclusive monitor
|
||||
// to wake up the processor in WFE.
|
||||
DPRINTF(LLSC,"Clearing lock and signaling sev\n");
|
||||
xc->setMiscReg(MISCREG_LOCKFLAG, false);
|
||||
// Implement ARMv8 WFE/SEV semantics
|
||||
sendEvent(xc);
|
||||
xc->setMiscReg(MISCREG_SEV_MAILBOX, true);
|
||||
}
|
||||
|
||||
} // namespace ArmISA
|
||||
} // namespace gem5
|
||||
|
||||
#endif
|
||||
@@ -44,8 +44,6 @@
|
||||
|
||||
#include "cpu/reg_class.hh"
|
||||
#include "enums/VecRegRenameMode.hh"
|
||||
#include "mem/packet.hh"
|
||||
#include "mem/request.hh"
|
||||
#include "sim/sim_object.hh"
|
||||
|
||||
namespace gem5
|
||||
@@ -86,19 +84,6 @@ class BaseISA : public SimObject
|
||||
}
|
||||
|
||||
const RegClasses ®Classes() const { return _regClasses; }
|
||||
|
||||
// Locked memory handling functions.
|
||||
virtual void handleLockedRead(const RequestPtr &req) {}
|
||||
virtual bool
|
||||
handleLockedWrite(const RequestPtr &req, Addr cacheBlockMask)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void handleLockedSnoop(PacketPtr pkt, Addr cacheBlockMask) {}
|
||||
virtual void handleLockedSnoopHit() {}
|
||||
|
||||
virtual void globalClearExclusive() {}
|
||||
};
|
||||
|
||||
} // namespace gem5
|
||||
|
||||
101
src/arch/generic/locked_mem.hh
Normal file
101
src/arch/generic/locked_mem.hh
Normal file
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright (c) 2017 ARM Limited
|
||||
* All rights reserved
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
* not be construed as granting a license to any other intellectual
|
||||
* property including but not limited to intellectual property relating
|
||||
* to a hardware implementation of the functionality of the software
|
||||
* licensed hereunder. You may use the software subject to the license
|
||||
* terms below provided that you ensure that this notice is replicated
|
||||
* unmodified and in its entirety in all distributions of the software,
|
||||
* modified or unmodified, in source code or in binary form.
|
||||
*
|
||||
* Copyright (c) 2006 The Regents of The University of Michigan
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met: redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer;
|
||||
* redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution;
|
||||
* neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef __ARCH_GENERIC_LOCKED_MEM_HH__
|
||||
#define __ARCH_GENERIC_LOCKED_MEM_HH__
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* Generic helper functions for locked memory accesses.
|
||||
*/
|
||||
|
||||
#include "base/compiler.hh"
|
||||
#include "mem/packet.hh"
|
||||
#include "mem/request.hh"
|
||||
|
||||
namespace gem5
|
||||
{
|
||||
|
||||
namespace GenericISA
|
||||
{
|
||||
|
||||
GEM5_DEPRECATED_NAMESPACE(LockedMem, locked_mem);
|
||||
namespace locked_mem
|
||||
{
|
||||
|
||||
template <class XC>
|
||||
inline void
|
||||
handleLockedSnoop(XC *xc, PacketPtr pkt, Addr cacheBlockMask)
|
||||
{
|
||||
}
|
||||
|
||||
template <class XC>
|
||||
inline void
|
||||
handleLockedRead(XC *xc, const RequestPtr &req)
|
||||
{
|
||||
}
|
||||
|
||||
template <class XC>
|
||||
inline void
|
||||
handleLockedSnoopHit(XC *xc)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
template <class XC>
|
||||
inline bool
|
||||
handleLockedWrite(XC *xc, const RequestPtr &req, Addr cacheBlockMask)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class XC>
|
||||
inline void
|
||||
globalClearExclusive(XC *xc)
|
||||
{
|
||||
}
|
||||
|
||||
} // namespace locked_mem
|
||||
|
||||
} // namespace Generic ISA
|
||||
} // namespace gem5
|
||||
|
||||
#endif
|
||||
154
src/arch/mips/locked_mem.hh
Normal file
154
src/arch/mips/locked_mem.hh
Normal file
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
* Copyright (c) 2012 ARM Limited
|
||||
* All rights reserved
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
* not be construed as granting a license to any other intellectual
|
||||
* property including but not limited to intellectual property relating
|
||||
* to a hardware implementation of the functionality of the software
|
||||
* licensed hereunder. You may use the software subject to the license
|
||||
* terms below provided that you ensure that this notice is replicated
|
||||
* unmodified and in its entirety in all distributions of the software,
|
||||
* modified or unmodified, in source code or in binary form.
|
||||
*
|
||||
* Copyright (c) 2006-2007 The Regents of The University of Michigan
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met: redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer;
|
||||
* redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution;
|
||||
* neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef __ARCH_MIPS_LOCKED_MEM_HH__
|
||||
#define __ARCH_MIPS_LOCKED_MEM_HH__
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* ISA-specific helper functions for locked memory accesses.
|
||||
*/
|
||||
|
||||
#include "arch/mips/regs/misc.hh"
|
||||
#include "base/logging.hh"
|
||||
#include "base/trace.hh"
|
||||
#include "cpu/base.hh"
|
||||
#include "debug/LLSC.hh"
|
||||
#include "mem/packet.hh"
|
||||
#include "mem/request.hh"
|
||||
|
||||
namespace gem5
|
||||
{
|
||||
|
||||
namespace MipsISA
|
||||
{
|
||||
template <class XC>
|
||||
inline void
|
||||
handleLockedSnoop(XC *xc, PacketPtr pkt, Addr cacheBlockMask)
|
||||
{
|
||||
if (!xc->readMiscReg(MISCREG_LLFLAG))
|
||||
return;
|
||||
|
||||
Addr locked_addr = xc->readMiscReg(MISCREG_LLADDR) & cacheBlockMask;
|
||||
Addr snoop_addr = pkt->getAddr() & cacheBlockMask;
|
||||
|
||||
if (locked_addr == snoop_addr)
|
||||
xc->setMiscReg(MISCREG_LLFLAG, false);
|
||||
}
|
||||
|
||||
|
||||
template <class XC>
|
||||
inline void
|
||||
handleLockedRead(XC *xc, const RequestPtr &req)
|
||||
{
|
||||
xc->setMiscReg(MISCREG_LLADDR, req->getPaddr() & ~0xf);
|
||||
xc->setMiscReg(MISCREG_LLFLAG, true);
|
||||
DPRINTF(LLSC, "[cid:%i]: Load-Link Flag Set & Load-Link"
|
||||
" Address set to %x.\n",
|
||||
req->contextId(), req->getPaddr() & ~0xf);
|
||||
}
|
||||
|
||||
template <class XC>
|
||||
inline void
|
||||
handleLockedSnoopHit(XC *xc)
|
||||
{
|
||||
}
|
||||
|
||||
template <class XC>
|
||||
inline bool
|
||||
handleLockedWrite(XC *xc, const RequestPtr &req, Addr cacheBlockMask)
|
||||
{
|
||||
if (req->isUncacheable()) {
|
||||
// Funky Turbolaser mailbox access...don't update
|
||||
// result register (see stq_c in decoder.isa)
|
||||
req->setExtraData(2);
|
||||
} else {
|
||||
// standard store conditional
|
||||
bool lock_flag = xc->readMiscReg(MISCREG_LLFLAG);
|
||||
Addr lock_addr = xc->readMiscReg(MISCREG_LLADDR);
|
||||
|
||||
if (!lock_flag || (req->getPaddr() & ~0xf) != lock_addr) {
|
||||
// Lock flag not set or addr mismatch in CPU;
|
||||
// don't even bother sending to memory system
|
||||
req->setExtraData(0);
|
||||
xc->setMiscReg(MISCREG_LLFLAG, false);
|
||||
|
||||
// the rest of this code is not architectural;
|
||||
// it's just a debugging aid to help detect
|
||||
// livelock by warning on long sequences of failed
|
||||
// store conditionals
|
||||
int stCondFailures = xc->readStCondFailures();
|
||||
stCondFailures++;
|
||||
xc->setStCondFailures(stCondFailures);
|
||||
if (stCondFailures % 100000 == 0) {
|
||||
warn("%i: context %d: %d consecutive "
|
||||
"store conditional failures\n",
|
||||
curTick(), xc->contextId(), stCondFailures);
|
||||
}
|
||||
|
||||
if (!lock_flag){
|
||||
DPRINTF(LLSC, "[cid:%i]: Lock Flag Set, "
|
||||
"Store Conditional Failed.\n",
|
||||
req->contextId());
|
||||
} else if ((req->getPaddr() & ~0xf) != lock_addr) {
|
||||
DPRINTF(LLSC, "[cid:%i]: Load-Link Address Mismatch, "
|
||||
"Store Conditional Failed.\n",
|
||||
req->contextId());
|
||||
}
|
||||
// store conditional failed already, so don't issue it to mem
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class XC>
|
||||
inline void
|
||||
globalClearExclusive(XC *xc)
|
||||
{
|
||||
xc->getCpuPtr()->wakeup(xc->threadId());
|
||||
}
|
||||
|
||||
} // namespace MipsISA
|
||||
} // namespace gem5
|
||||
|
||||
#endif
|
||||
63
src/arch/null/locked_mem.hh
Normal file
63
src/arch/null/locked_mem.hh
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (c) 2017 ARM Limited
|
||||
* All rights reserved
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
* not be construed as granting a license to any other intellectual
|
||||
* property including but not limited to intellectual property relating
|
||||
* to a hardware implementation of the functionality of the software
|
||||
* licensed hereunder. You may use the software subject to the license
|
||||
* terms below provided that you ensure that this notice is replicated
|
||||
* unmodified and in its entirety in all distributions of the software,
|
||||
* modified or unmodified, in source code or in binary form.
|
||||
*
|
||||
* Copyright (c) 2006 The Regents of The University of Michigan
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met: redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer;
|
||||
* redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution;
|
||||
* neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef __ARCH_NULL_LOCKED_MEM_HH__
|
||||
#define __ARCH_NULL_LOCKED_MEM_HH__
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* ISA-specific helper functions for locked memory accesses.
|
||||
*/
|
||||
|
||||
#include "arch/generic/locked_mem.hh"
|
||||
|
||||
namespace gem5
|
||||
{
|
||||
|
||||
namespace NullISA
|
||||
{
|
||||
|
||||
using namespace GenericISA::locked_mem;
|
||||
|
||||
} // namespace NullISA
|
||||
} // namespace gem5
|
||||
|
||||
#endif
|
||||
53
src/arch/power/locked_mem.hh
Normal file
53
src/arch/power/locked_mem.hh
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (c) 2006 The Regents of The University of Michigan
|
||||
* Copyright (c) 2007-2008 The Florida State University
|
||||
* Copyright (c) 2009 The University of Edinburgh
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met: redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer;
|
||||
* redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution;
|
||||
* neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef __ARCH_POWER_LOCKED_MEM_HH__
|
||||
#define __ARCH_POWER_LOCKED_MEM_HH__
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* ISA-specific helper functions for locked memory accesses.
|
||||
*/
|
||||
|
||||
#include "arch/generic/locked_mem.hh"
|
||||
|
||||
namespace gem5
|
||||
{
|
||||
|
||||
namespace PowerISA
|
||||
{
|
||||
|
||||
using namespace GenericISA::locked_mem;
|
||||
|
||||
} // namespace PowerISA
|
||||
} // namespace gem5
|
||||
|
||||
#endif // __ARCH_POWER_LOCKED_MEM_HH__
|
||||
@@ -47,6 +47,7 @@ if env['TARGET_ISA'] == 'riscv':
|
||||
Source('decoder.cc')
|
||||
Source('faults.cc')
|
||||
Source('isa.cc')
|
||||
Source('locked_mem.cc')
|
||||
Source('process.cc')
|
||||
Source('pagetable.cc')
|
||||
Source('pagetable_walker.cc')
|
||||
|
||||
@@ -43,14 +43,9 @@
|
||||
#include "arch/riscv/regs/misc.hh"
|
||||
#include "base/bitfield.hh"
|
||||
#include "base/compiler.hh"
|
||||
#include "base/logging.hh"
|
||||
#include "base/trace.hh"
|
||||
#include "cpu/base.hh"
|
||||
#include "debug/Checkpoint.hh"
|
||||
#include "debug/LLSC.hh"
|
||||
#include "debug/RiscvMisc.hh"
|
||||
#include "mem/packet.hh"
|
||||
#include "mem/request.hh"
|
||||
#include "params/RiscvISA.hh"
|
||||
#include "sim/pseudo_inst.hh"
|
||||
|
||||
@@ -489,76 +484,5 @@ ISA::unserialize(CheckpointIn &cp)
|
||||
UNSERIALIZE_CONTAINER(miscRegFile);
|
||||
}
|
||||
|
||||
const int WARN_FAILURE = 10000;
|
||||
|
||||
// RISC-V allows multiple locks per hart, but each SC has to unlock the most
|
||||
// recent one, so we use a stack here.
|
||||
std::unordered_map<int, std::stack<Addr>> locked_addrs;
|
||||
|
||||
void
|
||||
ISA::handleLockedSnoop(PacketPtr pkt, Addr cacheBlockMask)
|
||||
{
|
||||
std::stack<Addr>& locked_addr_stack = locked_addrs[tc->contextId()];
|
||||
|
||||
if (locked_addr_stack.empty())
|
||||
return;
|
||||
Addr snoop_addr = pkt->getAddr() & cacheBlockMask;
|
||||
DPRINTF(LLSC, "Locked snoop on address %x.\n", snoop_addr);
|
||||
if ((locked_addr_stack.top() & cacheBlockMask) == snoop_addr)
|
||||
locked_addr_stack.pop();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ISA::handleLockedRead(const RequestPtr &req)
|
||||
{
|
||||
std::stack<Addr>& locked_addr_stack = locked_addrs[tc->contextId()];
|
||||
|
||||
locked_addr_stack.push(req->getPaddr() & ~0xF);
|
||||
DPRINTF(LLSC, "[cid:%d]: Reserved address %x.\n",
|
||||
req->contextId(), req->getPaddr() & ~0xF);
|
||||
}
|
||||
|
||||
bool
|
||||
ISA::handleLockedWrite(const RequestPtr &req, Addr cacheBlockMask)
|
||||
{
|
||||
std::stack<Addr>& locked_addr_stack = locked_addrs[tc->contextId()];
|
||||
|
||||
// Normally RISC-V uses zero to indicate success and nonzero to indicate
|
||||
// failure (right now only 1 is reserved), but in gem5 zero indicates
|
||||
// failure and one indicates success, so here we conform to that (it should
|
||||
// be switched in the instruction's implementation)
|
||||
|
||||
DPRINTF(LLSC, "[cid:%d]: locked_addrs empty? %s.\n", req->contextId(),
|
||||
locked_addr_stack.empty() ? "yes" : "no");
|
||||
if (!locked_addr_stack.empty()) {
|
||||
DPRINTF(LLSC, "[cid:%d]: addr = %x.\n", req->contextId(),
|
||||
req->getPaddr() & ~0xF);
|
||||
DPRINTF(LLSC, "[cid:%d]: last locked addr = %x.\n", req->contextId(),
|
||||
locked_addr_stack.top());
|
||||
}
|
||||
if (locked_addr_stack.empty()
|
||||
|| locked_addr_stack.top() != ((req->getPaddr() & ~0xF))) {
|
||||
req->setExtraData(0);
|
||||
int stCondFailures = tc->readStCondFailures();
|
||||
tc->setStCondFailures(++stCondFailures);
|
||||
if (stCondFailures % WARN_FAILURE == 0) {
|
||||
warn("%i: context %d: %d consecutive SC failures.\n",
|
||||
curTick(), tc->contextId(), stCondFailures);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (req->isUncacheable()) {
|
||||
req->setExtraData(2);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
ISA::globalClearExclusive()
|
||||
{
|
||||
tc->getCpuPtr()->wakeup(tc->threadId());
|
||||
}
|
||||
|
||||
} // namespace RiscvISA
|
||||
} // namespace gem5
|
||||
|
||||
@@ -98,15 +98,6 @@ class ISA : public BaseISA
|
||||
void unserialize(CheckpointIn &cp) override;
|
||||
|
||||
ISA(const Params &p);
|
||||
|
||||
void handleLockedRead(const RequestPtr &req) override;
|
||||
|
||||
bool handleLockedWrite(const RequestPtr &req,
|
||||
Addr cacheBlockMask) override;
|
||||
|
||||
void handleLockedSnoop(PacketPtr pkt, Addr cacheBlockMask) override;
|
||||
|
||||
void globalClearExclusive() override;
|
||||
};
|
||||
|
||||
} // namespace RiscvISA
|
||||
|
||||
14
src/arch/riscv/locked_mem.cc
Normal file
14
src/arch/riscv/locked_mem.cc
Normal file
@@ -0,0 +1,14 @@
|
||||
#include "arch/riscv/locked_mem.hh"
|
||||
|
||||
#include <stack>
|
||||
|
||||
#include "base/types.hh"
|
||||
|
||||
namespace gem5
|
||||
{
|
||||
|
||||
namespace RiscvISA
|
||||
{
|
||||
std::unordered_map<int, std::stack<Addr>> locked_addrs;
|
||||
} // namespace RiscvISA
|
||||
} // namespace gem5
|
||||
147
src/arch/riscv/locked_mem.hh
Normal file
147
src/arch/riscv/locked_mem.hh
Normal file
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* Copyright (c) 2006 The Regents of The University of Michigan
|
||||
* Copyright (c) 2007-2008 The Florida State University
|
||||
* Copyright (c) 2009 The University of Edinburgh
|
||||
* Copyright (c) 2012 ARM Limited
|
||||
* Copyright (c) 2014-2015 Sven Karlsson
|
||||
* All rights reserved.
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
* not be construed as granting a license to any other intellectual
|
||||
* property including but not limited to intellectual property relating
|
||||
* to a hardware implementation of the functionality of the software
|
||||
* licensed hereunder. You may use the software subject to the license
|
||||
* terms below provided that you ensure that this notice is replicated
|
||||
* unmodified and in its entirety in all distributions of the software,
|
||||
* modified or unmodified, in source code or in binary form.
|
||||
*
|
||||
* Copyright (c) 2006-2007 The Regents of The University of Michigan
|
||||
* Copyright (c) 2016 The University of Virginia
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met: redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer;
|
||||
* redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution;
|
||||
* neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef __ARCH_RISCV_LOCKED_MEM_HH__
|
||||
#define __ARCH_RISCV_LOCKED_MEM_HH__
|
||||
|
||||
#include <stack>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "base/logging.hh"
|
||||
#include "base/trace.hh"
|
||||
#include "cpu/base.hh"
|
||||
#include "debug/LLSC.hh"
|
||||
#include "mem/packet.hh"
|
||||
#include "mem/request.hh"
|
||||
|
||||
namespace gem5
|
||||
{
|
||||
|
||||
/*
|
||||
* ISA-specific helper functions for locked memory accesses.
|
||||
*/
|
||||
namespace RiscvISA
|
||||
{
|
||||
|
||||
const int WARN_FAILURE = 10000;
|
||||
|
||||
// RISC-V allows multiple locks per hart, but each SC has to unlock the most
|
||||
// recent one, so we use a stack here.
|
||||
extern std::unordered_map<int, std::stack<Addr>> locked_addrs;
|
||||
|
||||
template <class XC> inline void
|
||||
handleLockedSnoop(XC *xc, PacketPtr pkt, Addr cacheBlockMask)
|
||||
{
|
||||
std::stack<Addr>& locked_addr_stack = locked_addrs[xc->contextId()];
|
||||
|
||||
if (locked_addr_stack.empty())
|
||||
return;
|
||||
Addr snoop_addr = pkt->getAddr() & cacheBlockMask;
|
||||
DPRINTF(LLSC, "Locked snoop on address %x.\n", snoop_addr);
|
||||
if ((locked_addr_stack.top() & cacheBlockMask) == snoop_addr)
|
||||
locked_addr_stack.pop();
|
||||
}
|
||||
|
||||
|
||||
template <class XC> inline void
|
||||
handleLockedRead(XC *xc, const RequestPtr &req)
|
||||
{
|
||||
std::stack<Addr>& locked_addr_stack = locked_addrs[xc->contextId()];
|
||||
|
||||
locked_addr_stack.push(req->getPaddr() & ~0xF);
|
||||
DPRINTF(LLSC, "[cid:%d]: Reserved address %x.\n",
|
||||
req->contextId(), req->getPaddr() & ~0xF);
|
||||
}
|
||||
|
||||
template <class XC> inline void
|
||||
handleLockedSnoopHit(XC *xc)
|
||||
{}
|
||||
|
||||
template <class XC> inline bool
|
||||
handleLockedWrite(XC *xc, const RequestPtr &req, Addr cacheBlockMask)
|
||||
{
|
||||
std::stack<Addr>& locked_addr_stack = locked_addrs[xc->contextId()];
|
||||
|
||||
// Normally RISC-V uses zero to indicate success and nonzero to indicate
|
||||
// failure (right now only 1 is reserved), but in gem5 zero indicates
|
||||
// failure and one indicates success, so here we conform to that (it should
|
||||
// be switched in the instruction's implementation)
|
||||
|
||||
DPRINTF(LLSC, "[cid:%d]: locked_addrs empty? %s.\n", req->contextId(),
|
||||
locked_addr_stack.empty() ? "yes" : "no");
|
||||
if (!locked_addr_stack.empty()) {
|
||||
DPRINTF(LLSC, "[cid:%d]: addr = %x.\n", req->contextId(),
|
||||
req->getPaddr() & ~0xF);
|
||||
DPRINTF(LLSC, "[cid:%d]: last locked addr = %x.\n", req->contextId(),
|
||||
locked_addr_stack.top());
|
||||
}
|
||||
if (locked_addr_stack.empty()
|
||||
|| locked_addr_stack.top() != ((req->getPaddr() & ~0xF))) {
|
||||
req->setExtraData(0);
|
||||
int stCondFailures = xc->readStCondFailures();
|
||||
xc->setStCondFailures(++stCondFailures);
|
||||
if (stCondFailures % WARN_FAILURE == 0) {
|
||||
warn("%i: context %d: %d consecutive SC failures.\n",
|
||||
curTick(), xc->contextId(), stCondFailures);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (req->isUncacheable()) {
|
||||
req->setExtraData(2);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class XC>
|
||||
inline void
|
||||
globalClearExclusive(XC *xc)
|
||||
{
|
||||
xc->getCpuPtr()->wakeup(xc->threadId());
|
||||
}
|
||||
|
||||
} // namespace RiscvISA
|
||||
} // namespace gem5
|
||||
|
||||
#endif // __ARCH_RISCV_LOCKED_MEM_HH__
|
||||
51
src/arch/sparc/locked_mem.hh
Normal file
51
src/arch/sparc/locked_mem.hh
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (c) 2006 The Regents of The University of Michigan
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met: redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer;
|
||||
* redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution;
|
||||
* neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef __ARCH_SPARC_LOCKED_MEM_HH__
|
||||
#define __ARCH_SPARC_LOCKED_MEM_HH__
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* ISA-specific helper functions for locked memory accesses.
|
||||
*/
|
||||
|
||||
#include "arch/generic/locked_mem.hh"
|
||||
|
||||
namespace gem5
|
||||
{
|
||||
|
||||
namespace SparcISA
|
||||
{
|
||||
|
||||
using namespace GenericISA::locked_mem;
|
||||
|
||||
} // namespace SparcISA
|
||||
} // namespace gem5
|
||||
|
||||
#endif
|
||||
51
src/arch/x86/locked_mem.hh
Normal file
51
src/arch/x86/locked_mem.hh
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (c) 2006 The Regents of The University of Michigan
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met: redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer;
|
||||
* redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution;
|
||||
* neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef __ARCH_X86_LOCKEDMEM_HH__
|
||||
#define __ARCH_X86_LOCKEDMEM_HH__
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* ISA-specific helper functions for locked memory accesses.
|
||||
*/
|
||||
|
||||
#include "arch/generic/locked_mem.hh"
|
||||
|
||||
namespace gem5
|
||||
{
|
||||
|
||||
namespace X86ISA
|
||||
{
|
||||
|
||||
using namespace GenericISA::locked_mem;
|
||||
|
||||
} // namespace X86ISA
|
||||
} // namespace gem5
|
||||
|
||||
#endif // __ARCH_X86_LOCKEDMEM_HH__
|
||||
@@ -40,6 +40,7 @@
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
|
||||
#include "arch/locked_mem.hh"
|
||||
#include "base/compiler.hh"
|
||||
#include "base/logging.hh"
|
||||
#include "base/trace.hh"
|
||||
@@ -1136,10 +1137,10 @@ LSQ::tryToSendToTransfers(LSQRequestPtr request)
|
||||
|
||||
/* Handle LLSC requests and tests */
|
||||
if (is_load) {
|
||||
thread.getIsaPtr()->handleLockedRead(request->request);
|
||||
TheISA::handleLockedRead(&context, request->request);
|
||||
} else {
|
||||
do_access = thread.getIsaPtr()->handleLockedWrite(request->request,
|
||||
cacheBlockMask);
|
||||
do_access = TheISA::handleLockedWrite(&context,
|
||||
request->request, cacheBlockMask);
|
||||
|
||||
if (!do_access) {
|
||||
DPRINTF(MinorMem, "Not perfoming a memory "
|
||||
@@ -1768,8 +1769,8 @@ LSQ::recvTimingSnoopReq(PacketPtr pkt)
|
||||
|
||||
if (pkt->isInvalidate() || pkt->isWrite()) {
|
||||
for (ThreadID tid = 0; tid < cpu.numThreads; tid++) {
|
||||
cpu.getContext(tid)->getIsaPtr()->handleLockedSnoop(
|
||||
pkt, cacheBlockMask);
|
||||
TheISA::handleLockedSnoop(cpu.getContext(tid), pkt,
|
||||
cacheBlockMask);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1790,8 +1791,8 @@ LSQ::threadSnoop(LSQRequestPtr request)
|
||||
}
|
||||
|
||||
if (pkt->isInvalidate() || pkt->isWrite()) {
|
||||
cpu.getContext(tid)->getIsaPtr()->handleLockedSnoop(pkt,
|
||||
cacheBlockMask);
|
||||
TheISA::handleLockedSnoop(cpu.getContext(tid), pkt,
|
||||
cacheBlockMask);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
#include "cpu/o3/lsq_unit.hh"
|
||||
|
||||
#include "arch/generic/debugfaults.hh"
|
||||
#include "arch/locked_mem.hh"
|
||||
#include "base/str.hh"
|
||||
#include "config/the_isa.hh"
|
||||
#include "cpu/checker/cpu.hh"
|
||||
@@ -451,7 +452,7 @@ LSQUnit::checkSnoop(PacketPtr pkt)
|
||||
gem5::ThreadContext *tc = cpu->getContext(x);
|
||||
bool no_squash = cpu->thread[x]->noSquashFromTC;
|
||||
cpu->thread[x]->noSquashFromTC = true;
|
||||
tc->getIsaPtr()->handleLockedSnoop(pkt, cacheBlockMask);
|
||||
TheISA::handleLockedSnoop(tc, pkt, cacheBlockMask);
|
||||
cpu->thread[x]->noSquashFromTC = no_squash;
|
||||
}
|
||||
|
||||
@@ -469,9 +470,8 @@ LSQUnit::checkSnoop(PacketPtr pkt)
|
||||
// Check that this snoop didn't just invalidate our lock flag
|
||||
if (ld_inst->effAddrValid() &&
|
||||
req->isCacheBlockHit(invalidate_addr, cacheBlockMask)
|
||||
&& ld_inst->memReqFlags & Request::LLSC) {
|
||||
ld_inst->tcBase()->getIsaPtr()->handleLockedSnoopHit();
|
||||
}
|
||||
&& ld_inst->memReqFlags & Request::LLSC)
|
||||
TheISA::handleLockedSnoopHit(ld_inst.get());
|
||||
|
||||
bool force_squash = false;
|
||||
|
||||
@@ -508,7 +508,7 @@ LSQUnit::checkSnoop(PacketPtr pkt)
|
||||
// address since the LOCK* flags don't get updated until
|
||||
// commit.
|
||||
if (ld_inst->memReqFlags & Request::LLSC)
|
||||
ld_inst->tcBase()->getIsaPtr()->handleLockedSnoopHit();
|
||||
TheISA::handleLockedSnoopHit(ld_inst.get());
|
||||
|
||||
// If a older load checks this and it's true
|
||||
// then we might have missed the snoop
|
||||
@@ -882,7 +882,7 @@ LSQUnit::writebackStores()
|
||||
// misc regs normally updates the result, but this is not
|
||||
// the desired behavior when handling store conditionals.
|
||||
inst->recordResult(false);
|
||||
bool success = inst->tcBase()->getIsaPtr()->handleLockedWrite(
|
||||
bool success = TheISA::handleLockedWrite(inst.get(),
|
||||
req->request(), cacheBlockMask);
|
||||
inst->recordResult(true);
|
||||
req->packetSent();
|
||||
@@ -1348,7 +1348,7 @@ LSQUnit::read(LSQRequest *req, int load_idx)
|
||||
// regs normally updates the result, but this is not the
|
||||
// desired behavior when handling store conditionals.
|
||||
load_inst->recordResult(false);
|
||||
load_inst->tcBase()->getIsaPtr()->handleLockedRead(req->mainRequest());
|
||||
TheISA::handleLockedRead(load_inst.get(), req->mainRequest());
|
||||
load_inst->recordResult(true);
|
||||
}
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
|
||||
#include "cpu/simple/atomic.hh"
|
||||
|
||||
#include "arch/locked_mem.hh"
|
||||
#include "base/output.hh"
|
||||
#include "config/the_isa.hh"
|
||||
#include "cpu/exetrace.hh"
|
||||
@@ -132,8 +133,8 @@ AtomicSimpleCPU::threadSnoop(PacketPtr pkt, ThreadID sender)
|
||||
wakeup(tid);
|
||||
}
|
||||
|
||||
threadInfo[tid]->thread->getIsaPtr()->handleLockedSnoop(pkt,
|
||||
dcachePort.cacheBlockMask);
|
||||
TheISA::handleLockedSnoop(threadInfo[tid]->thread,
|
||||
pkt, dcachePort.cacheBlockMask);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -297,8 +298,7 @@ AtomicSimpleCPU::AtomicCPUDPort::recvAtomicSnoop(PacketPtr pkt)
|
||||
DPRINTF(SimpleCPU, "received invalidation for addr:%#x\n",
|
||||
pkt->getAddr());
|
||||
for (auto &t_info : cpu->threadInfo) {
|
||||
t_info->thread->getIsaPtr()->handleLockedSnoop(pkt,
|
||||
cacheBlockMask);
|
||||
TheISA::handleLockedSnoop(t_info->thread, pkt, cacheBlockMask);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -324,8 +324,7 @@ AtomicSimpleCPU::AtomicCPUDPort::recvFunctionalSnoop(PacketPtr pkt)
|
||||
DPRINTF(SimpleCPU, "received invalidation for addr:%#x\n",
|
||||
pkt->getAddr());
|
||||
for (auto &t_info : cpu->threadInfo) {
|
||||
t_info->thread->getIsaPtr()->handleLockedSnoop(pkt,
|
||||
cacheBlockMask);
|
||||
TheISA::handleLockedSnoop(t_info->thread, pkt, cacheBlockMask);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -408,7 +407,7 @@ AtomicSimpleCPU::readMem(Addr addr, uint8_t *data, unsigned size,
|
||||
assert(!pkt.isError());
|
||||
|
||||
if (req->isLLSC()) {
|
||||
thread->getIsaPtr()->handleLockedRead(req);
|
||||
TheISA::handleLockedRead(thread, req);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -483,8 +482,9 @@ AtomicSimpleCPU::writeMem(uint8_t *data, unsigned size, Addr addr,
|
||||
|
||||
if (req->isLLSC()) {
|
||||
assert(curr_frag_id == 0);
|
||||
do_access = thread->getIsaPtr()->handleLockedWrite(req,
|
||||
dcachePort.cacheBlockMask);
|
||||
do_access =
|
||||
TheISA::handleLockedWrite(thread, req,
|
||||
dcachePort.cacheBlockMask);
|
||||
} else if (req->isSwap()) {
|
||||
assert(curr_frag_id == 0);
|
||||
if (req->isCondSwap()) {
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
|
||||
#include "cpu/simple/timing.hh"
|
||||
|
||||
#include "arch/locked_mem.hh"
|
||||
#include "base/compiler.hh"
|
||||
#include "config/the_isa.hh"
|
||||
#include "cpu/exetrace.hh"
|
||||
@@ -275,7 +276,7 @@ TimingSimpleCPU::handleReadPacket(PacketPtr pkt)
|
||||
// We're about the issues a locked load, so tell the monitor
|
||||
// to start caring about this address
|
||||
if (pkt->isRead() && pkt->req->isLLSC()) {
|
||||
thread->getIsaPtr()->handleLockedRead(pkt->req);
|
||||
TheISA::handleLockedRead(thread, pkt->req);
|
||||
}
|
||||
if (req->isLocalAccess()) {
|
||||
Cycles delay = req->localAccessor(thread->getTC(), pkt);
|
||||
@@ -324,8 +325,7 @@ TimingSimpleCPU::sendData(const RequestPtr &req, uint8_t *data, uint64_t *res,
|
||||
bool do_access = true; // flag to suppress cache access
|
||||
|
||||
if (req->isLLSC()) {
|
||||
do_access = thread->getIsaPtr()->handleLockedWrite(
|
||||
req, dcachePort.cacheBlockMask);
|
||||
do_access = TheISA::handleLockedWrite(thread, req, dcachePort.cacheBlockMask);
|
||||
} else if (req->isCondSwap()) {
|
||||
assert(res);
|
||||
req->setExtraData(*res);
|
||||
@@ -641,7 +641,7 @@ TimingSimpleCPU::threadSnoop(PacketPtr pkt, ThreadID sender)
|
||||
if (getCpuAddrMonitor(tid)->doMonitor(pkt)) {
|
||||
wakeup(tid);
|
||||
}
|
||||
threadInfo[tid]->thread->getIsaPtr()->handleLockedSnoop(pkt,
|
||||
TheISA::handleLockedSnoop(threadInfo[tid]->thread, pkt,
|
||||
dcachePort.cacheBlockMask);
|
||||
}
|
||||
}
|
||||
@@ -1100,8 +1100,7 @@ TimingSimpleCPU::DcachePort::recvTimingSnoopReq(PacketPtr pkt)
|
||||
// It is not necessary to wake up the processor on all incoming packets
|
||||
if (pkt->isInvalidate() || pkt->isWrite()) {
|
||||
for (auto &t_info : cpu->threadInfo) {
|
||||
t_info->thread->getIsaPtr()->handleLockedSnoop(pkt,
|
||||
cacheBlockMask);
|
||||
TheISA::handleLockedSnoop(t_info->thread, pkt, cacheBlockMask);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "arch/locked_mem.hh"
|
||||
#include "base/loader/memory_image.hh"
|
||||
#include "base/loader/object_file.hh"
|
||||
#include "cpu/thread_context.hh"
|
||||
@@ -338,7 +339,7 @@ AbstractMemory::checkLockedAddrList(PacketPtr pkt)
|
||||
InvalidContextID;
|
||||
if (owner_cid != requestor_cid) {
|
||||
ThreadContext* ctx = system()->threads[owner_cid];
|
||||
ctx->getIsaPtr()->globalClearExclusive();
|
||||
TheISA::globalClearExclusive(ctx);
|
||||
}
|
||||
i = lockedAddrList.erase(i);
|
||||
} else {
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
#include <csignal>
|
||||
|
||||
#include "arch/decoder.hh"
|
||||
#include "arch/locked_mem.hh"
|
||||
#include "base/logging.hh"
|
||||
#include "cpu/base.hh"
|
||||
#include "cpu/thread_context.hh"
|
||||
@@ -125,7 +126,7 @@ void GenericHtmFailureFault::invoke(ThreadContext *tc,
|
||||
checkpoint->restore(tc, getHtmFailureFaultCause());
|
||||
|
||||
// reset the global monitor
|
||||
tc->getIsaPtr()->globalClearExclusive();
|
||||
TheISA::globalClearExclusive(tc);
|
||||
|
||||
// send abort packet to ruby (in final breath)
|
||||
tc->htmAbortTransaction(htmUid, cause);
|
||||
|
||||
Reference in New Issue
Block a user