ARM: Use CPU local lock before sending load to mem system.
This change uses the locked_mem.hh header to handle implementing CLREX. It simplifies the current implementation greatly.
This commit is contained in:
parent
6b69890493
commit
8af1eeec6f
5 changed files with 39 additions and 59 deletions
|
@ -680,18 +680,14 @@ let {{
|
|||
exec_output += PredOpExecute.subst(setendIop)
|
||||
|
||||
clrexCode = '''
|
||||
unsigned memAccessFlags = Request::CLEAR_LL |
|
||||
ArmISA::TLB::AlignWord | Request::LLSC;
|
||||
fault = xc->read(0, (uint32_t&)Mem, memAccessFlags);
|
||||
LLSCLock = 0;
|
||||
'''
|
||||
clrexIop = InstObjParams("clrex", "Clrex","PredOp",
|
||||
{ "code": clrexCode,
|
||||
"predicate_test": predicateTest },[])
|
||||
header_output += ClrexDeclare.subst(clrexIop)
|
||||
header_output += BasicDeclare.subst(clrexIop)
|
||||
decoder_output += BasicConstructor.subst(clrexIop)
|
||||
exec_output += PredOpExecute.subst(clrexIop)
|
||||
exec_output += ClrexInitiateAcc.subst(clrexIop)
|
||||
exec_output += ClrexCompleteAcc.subst(clrexIop)
|
||||
|
||||
isbCode = '''
|
||||
fault = new FlushPipe;
|
||||
|
|
|
@ -227,6 +227,7 @@ def operands {{
|
|||
'Fpexc': cntrlRegNC('MISCREG_FPEXC'),
|
||||
'Sctlr': cntrlRegNC('MISCREG_SCTLR'),
|
||||
'SevMailbox': cntrlRegNC('MISCREG_SEV_MAILBOX'),
|
||||
'LLSCLock': cntrlRegNC('MISCREG_LOCKFLAG'),
|
||||
|
||||
#Register fields for microops
|
||||
'URa' : intReg('ura'),
|
||||
|
|
|
@ -402,54 +402,3 @@ def template RegImmRegShiftOpConstructor {{
|
|||
}
|
||||
}};
|
||||
|
||||
def template ClrexDeclare {{
|
||||
/**
|
||||
* Static instruction class for "%(mnemonic)s".
|
||||
*/
|
||||
class %(class_name)s : public %(base_class)s
|
||||
{
|
||||
public:
|
||||
|
||||
/// Constructor.
|
||||
%(class_name)s(ExtMachInst machInst);
|
||||
|
||||
%(BasicExecDeclare)s
|
||||
|
||||
%(InitiateAccDeclare)s
|
||||
|
||||
%(CompleteAccDeclare)s
|
||||
};
|
||||
}};
|
||||
|
||||
def template ClrexInitiateAcc {{
|
||||
Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
|
||||
Trace::InstRecord *traceData) const
|
||||
{
|
||||
Fault fault = NoFault;
|
||||
%(op_decl)s;
|
||||
%(op_rd)s;
|
||||
|
||||
if (%(predicate_test)s)
|
||||
{
|
||||
if (fault == NoFault) {
|
||||
unsigned memAccessFlags = Request::CLEAR_LL |
|
||||
ArmISA::TLB::AlignWord | Request::LLSC;
|
||||
fault = xc->read(0, (uint32_t&)Mem, memAccessFlags);
|
||||
}
|
||||
} else {
|
||||
xc->setPredicate(false);
|
||||
}
|
||||
|
||||
return fault;
|
||||
}
|
||||
}};
|
||||
|
||||
def template ClrexCompleteAcc {{
|
||||
Fault %(class_name)s::completeAcc(PacketPtr pkt,
|
||||
%(CPU_exec_context)s *xc,
|
||||
Trace::InstRecord *traceData) const
|
||||
{
|
||||
return NoFault;
|
||||
}
|
||||
}};
|
||||
|
||||
|
|
|
@ -26,7 +26,8 @@
|
|||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Authors: Steve Reinhardt
|
||||
* Authors: Ali Saidi
|
||||
* Steve Reinhardt
|
||||
* Stephen Hines
|
||||
*/
|
||||
|
||||
|
@ -39,6 +40,7 @@
|
|||
* ISA-specific helper functions for locked memory accesses.
|
||||
*/
|
||||
|
||||
#include "arch/arm/miscregs.hh"
|
||||
#include "mem/request.hh"
|
||||
|
||||
|
||||
|
@ -48,6 +50,8 @@ template <class XC>
|
|||
inline void
|
||||
handleLockedRead(XC *xc, Request *req)
|
||||
{
|
||||
xc->setMiscReg(MISCREG_LOCKADDR, req->getPaddr() & ~0xf);
|
||||
xc->setMiscReg(MISCREG_LOCKFLAG, true);
|
||||
}
|
||||
|
||||
|
||||
|
@ -55,6 +59,34 @@ template <class XC>
|
|||
inline bool
|
||||
handleLockedWrite(XC *xc, Request *req)
|
||||
{
|
||||
if (req->isSwap())
|
||||
return true;
|
||||
|
||||
// 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);
|
||||
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_LOCKFLAG, 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("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;
|
||||
}
|
||||
|
||||
|
|
|
@ -171,6 +171,8 @@ namespace ArmISA
|
|||
MISCREG_ID_ISAR4,
|
||||
MISCREG_ID_ISAR5,
|
||||
MISCREG_CPSR_MODE,
|
||||
MISCREG_LOCKFLAG,
|
||||
MISCREG_LOCKADDR,
|
||||
MISCREG_CP15_UNIMP_START,
|
||||
MISCREG_TCMTR = MISCREG_CP15_UNIMP_START,
|
||||
MISCREG_ID_PFR1,
|
||||
|
@ -234,7 +236,7 @@ namespace ArmISA
|
|||
"pmceid1", "pmc_other", "pmxevcntr",
|
||||
"pmuserenr", "pmintenset", "pmintenclr",
|
||||
"id_isar0", "id_isar1", "id_isar2", "id_isar3", "id_isar4", "id_isar5",
|
||||
"cpsr_mode",
|
||||
"cpsr_mode", "lockflag", "lockaddr",
|
||||
// Unimplemented below
|
||||
"tcmtr",
|
||||
"id_pfr1", "id_dfr0", "id_afr0",
|
||||
|
|
Loading…
Reference in a new issue