From eeb36e5b6e81c6b9ea6a0c3c97573e762e58ae05 Mon Sep 17 00:00:00 2001 From: Nikos Nikoleris Date: Tue, 7 Feb 2017 11:35:10 +0000 Subject: arm: Add support for the mcr dc{ic,i,c}mvac, dccmvau instructions This patch adds support for the ARMv7 cache maintenance intructions: * mcr dccmvac cleans a VA to the PoC * mcr dcimvac invalidates a VA to the PoC * mcr dccimvac cleans and invalidates a VA to the PoC * mcr dccmvau cleans a VA to the PoU Change-Id: I6511f203039ca145cc9128ddf61d09d6d7e40c10 Reviewed-by: Stephan Diestelhorst Reviewed-by: Anouk Van Laer Reviewed-on: https://gem5-review.googlesource.com/5059 Maintainer: Andreas Sandberg Reviewed-by: Jason Lowe-Power --- src/arch/arm/insts/misc.cc | 12 ++++- src/arch/arm/insts/misc.hh | 19 ++++++- src/arch/arm/isa/formats/misc.isa | 13 +++-- src/arch/arm/isa/insts/misc.isa | 100 ++++++++++++++++++++++++++++++++++++ src/arch/arm/isa/templates/misc.isa | 83 +++++++++++++++++++++++++++++- 5 files changed, 220 insertions(+), 7 deletions(-) diff --git a/src/arch/arm/insts/misc.cc b/src/arch/arm/insts/misc.cc index ec1b9358c..ba97eff09 100644 --- a/src/arch/arm/insts/misc.cc +++ b/src/arch/arm/insts/misc.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2012-2013 ARM Limited + * Copyright (c) 2010, 2012-2013, 2017 ARM Limited * Copyright (c) 2013 Advanced Micro Devices, Inc. * All rights reserved * @@ -321,6 +321,16 @@ RegImmRegShiftOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const return ss.str(); } +std::string +MiscRegRegImmMemOp::generateDisassembly(Addr pc, + const SymbolTable *symtab) const +{ + std::stringstream ss; + printMnemonic(ss); + printIntReg(ss, op1); + return ss.str(); +} + std::string UnknownOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const { diff --git a/src/arch/arm/insts/misc.hh b/src/arch/arm/insts/misc.hh index c2dcaa847..72d1694c9 100644 --- a/src/arch/arm/insts/misc.hh +++ b/src/arch/arm/insts/misc.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2012-2013 ARM Limited + * Copyright (c) 2010, 2012-2013, 2017 ARM Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -344,6 +344,23 @@ class RegImmRegShiftOp : public PredOp std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; }; +class MiscRegRegImmMemOp : public PredOp +{ + protected: + MiscRegIndex dest; + IntRegIndex op1; + uint64_t imm; + + MiscRegRegImmMemOp(const char *mnem, ExtMachInst _machInst, + OpClass __opClass, MiscRegIndex _dest, IntRegIndex _op1, + uint64_t _imm) : + PredOp(mnem, _machInst, __opClass), + dest(_dest), op1(_op1), imm(_imm) + {} + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; +}; + class UnknownOp : public PredOp { protected: diff --git a/src/arch/arm/isa/formats/misc.isa b/src/arch/arm/isa/formats/misc.isa index 26681e40f..4f834b8e1 100644 --- a/src/arch/arm/isa/formats/misc.isa +++ b/src/arch/arm/isa/formats/misc.isa @@ -1,6 +1,6 @@ // -*- mode:c++ -*- -// Copyright (c) 2010-2013,2016 ARM Limited +// Copyright (c) 2010-2013,2016-2017 ARM Limited // All rights reserved // // The license below extends only to copyright in the software and shall @@ -219,15 +219,20 @@ let {{ machInst, csprintf("miscreg crn:%d opc1:%d crm:%d opc2:%d %s unknown", crn, opc1, crm, opc2, isRead ? "read" : "write")); - case MISCREG_DCCMVAC: - return new McrMrcMiscInst(isRead ? "mrc dccmvac" : "mcr dccmvac", - machInst, iss, MISCREG_DCCMVAC); case MISCREG_CP15ISB: return new Isb(machInst, iss); case MISCREG_CP15DSB: return new Dsb(machInst, iss); case MISCREG_CP15DMB: return new Dmb(machInst, iss); + case MISCREG_DCIMVAC: + return new McrDcimvac(machInst, miscReg, rt, iss); + case MISCREG_DCCMVAC: + return new McrDccmvac(machInst, miscReg, rt, iss); + case MISCREG_DCCMVAU: + return new McrDccmvau(machInst, miscReg, rt, iss); + case MISCREG_DCCIMVAC: + return new McrDccimvac(machInst, miscReg, rt, iss); default: if (miscRegInfo[miscReg][MISCREG_WARN_NOT_FAIL]) { std::string full_mnem = csprintf("%s %s", diff --git a/src/arch/arm/isa/insts/misc.isa b/src/arch/arm/isa/insts/misc.isa index 80ad6cdf4..ef0a6709e 100644 --- a/src/arch/arm/isa/insts/misc.isa +++ b/src/arch/arm/isa/insts/misc.isa @@ -1063,6 +1063,106 @@ let {{ decoder_output += BasicConstructor.subst(clrexIop) exec_output += PredOpExecute.subst(clrexIop) + McrDcCheckCode = ''' + int preFlatDest = flattenMiscRegNsBanked(dest, xc->tcBase()); + MiscRegIndex miscReg = (MiscRegIndex) xc->tcBase()->flattenRegId( + RegId(MiscRegClass, preFlatDest)).index(); + bool hypTrap = mcrMrc15TrapToHyp(miscReg, Hcr, Cpsr, Scr, Hdcr, Hstr, + Hcptr, imm); + bool can_write, undefined; + std::tie(can_write, undefined) = canWriteCoprocReg(miscReg, Scr, Cpsr); + + // if we're in non secure PL1 mode then we can trap regardless + // of whether the register is accessible, in other modes we + // trap if only if the register IS accessible. + if (undefined || (!can_write & !(hypTrap & !inUserMode(Cpsr) & + !inSecureState(Scr, Cpsr)))) { + return std::make_shared(machInst, false, + mnemonic); + } + if (hypTrap) { + return std::make_shared(machInst, imm, + EC_TRAPPED_CP15_MCR_MRC); + } + ''' + + McrDcimvacCode = ''' + const Request::Flags memAccessFlags(ArmISA::TLB::MustBeOne | + Request::INVALIDATE | + Request::DST_POC); + EA = Op1; + ''' + McrDcimvacIop = InstObjParams("mcr dcimvac", "McrDcimvac", + "MiscRegRegImmMemOp", + {"memacc_code": McrDcCheckCode, + "postacc_code": "", + "ea_code": McrDcimvacCode, + "predicate_test": predicateTest}, + ['IsMemRef', 'IsStore']) + header_output += MiscRegRegImmMemOpDeclare.subst(McrDcimvacIop) + decoder_output += MiscRegRegImmOpConstructor.subst(McrDcimvacIop) + exec_output += Mcr15Execute.subst(McrDcimvacIop) + \ + Mcr15InitiateAcc.subst(McrDcimvacIop) + \ + Mcr15CompleteAcc.subst(McrDcimvacIop) + + McrDccmvacCode = ''' + const Request::Flags memAccessFlags(ArmISA::TLB::MustBeOne | + Request::CLEAN | + Request::DST_POC); + EA = Op1; + ''' + McrDccmvacIop = InstObjParams("mcr dccmvac", "McrDccmvac", + "MiscRegRegImmMemOp", + {"memacc_code": McrDcCheckCode, + "postacc_code": "", + "ea_code": McrDccmvacCode, + "predicate_test": predicateTest}, + ['IsMemRef', 'IsStore']) + header_output += MiscRegRegImmMemOpDeclare.subst(McrDccmvacIop) + decoder_output += MiscRegRegImmOpConstructor.subst(McrDccmvacIop) + exec_output += Mcr15Execute.subst(McrDccmvacIop) + \ + Mcr15InitiateAcc.subst(McrDccmvacIop) + \ + Mcr15CompleteAcc.subst(McrDccmvacIop) + + McrDccmvauCode = ''' + const Request::Flags memAccessFlags(ArmISA::TLB::MustBeOne | + Request::CLEAN | + Request::DST_POU); + EA = Op1; + ''' + McrDccmvauIop = InstObjParams("mcr dccmvau", "McrDccmvau", + "MiscRegRegImmMemOp", + {"memacc_code": McrDcCheckCode, + "postacc_code": "", + "ea_code": McrDccmvauCode, + "predicate_test": predicateTest}, + ['IsMemRef', 'IsStore']) + header_output += MiscRegRegImmMemOpDeclare.subst(McrDccmvauIop) + decoder_output += MiscRegRegImmOpConstructor.subst(McrDccmvauIop) + exec_output += Mcr15Execute.subst(McrDccmvauIop) + \ + Mcr15InitiateAcc.subst(McrDccmvauIop) + \ + Mcr15CompleteAcc.subst(McrDccmvauIop) + + McrDccimvacCode = ''' + const Request::Flags memAccessFlags(ArmISA::TLB::MustBeOne | + Request::CLEAN | + Request::INVALIDATE | + Request::DST_POC); + EA = Op1; + ''' + McrDccimvacIop = InstObjParams("mcr dccimvac", "McrDccimvac", + "MiscRegRegImmMemOp", + {"memacc_code": McrDcCheckCode, + "postacc_code": "", + "ea_code": McrDccimvacCode, + "predicate_test": predicateTest}, + ['IsMemRef', 'IsStore']) + header_output += MiscRegRegImmMemOpDeclare.subst(McrDccimvacIop) + decoder_output += MiscRegRegImmOpConstructor.subst(McrDccimvacIop) + exec_output += Mcr15Execute.subst(McrDccimvacIop) + \ + Mcr15InitiateAcc.subst(McrDccimvacIop) + \ + Mcr15CompleteAcc.subst(McrDccimvacIop) + isbCode = ''' // If the barrier is due to a CP15 access check for hyp traps if ((imm != 0) && mcrMrc15TrapToHyp(MISCREG_CP15ISB, Hcr, Cpsr, Scr, diff --git a/src/arch/arm/isa/templates/misc.isa b/src/arch/arm/isa/templates/misc.isa index 0a23ba5d3..639ff3aca 100644 --- a/src/arch/arm/isa/templates/misc.isa +++ b/src/arch/arm/isa/templates/misc.isa @@ -1,6 +1,6 @@ // -*- mode:c++ -*- -// Copyright (c) 2010-2013 ARM Limited +// Copyright (c) 2010-2013,2017 ARM Limited // All rights reserved // // The license below extends only to copyright in the software and shall @@ -614,3 +614,84 @@ def template RegImmRegShiftOpConstructor {{ } }}; +def template MiscRegRegImmMemOpDeclare {{ + class %(class_name)s : public %(base_class)s + { + protected: + public: + // Constructor + %(class_name)s(ExtMachInst machInst, + MiscRegIndex _dest, IntRegIndex _op1, + uint64_t _imm); + Fault execute(ExecContext *, Trace::InstRecord *) const; + Fault initiateAcc(ExecContext *, Trace::InstRecord *) const; + Fault completeAcc(PacketPtr, ExecContext *, Trace::InstRecord *) const; + }; +}}; + +def template Mcr15Execute {{ + Fault %(class_name)s::execute(ExecContext *xc, + Trace::InstRecord *traceData) const + { + Addr EA; + Fault fault = NoFault; + + %(op_decl)s; + %(op_rd)s; + %(ea_code)s; + + if (%(predicate_test)s) { + if (fault == NoFault) { + %(memacc_code)s; + } + + if (fault == NoFault) { + Addr size = 64; + EA &= ~(size - 1); + fault = xc->writeMem(NULL, size, EA, memAccessFlags, NULL); + } + } else { + xc->setPredicate(false); + } + + return fault; + } +}}; + +def template Mcr15InitiateAcc {{ + Fault %(class_name)s::initiateAcc(ExecContext *xc, + Trace::InstRecord *traceData) const + { + Addr EA; + Fault fault = NoFault; + + %(op_decl)s; + %(op_rd)s; + %(ea_code)s; + + if (%(predicate_test)s) { + if (fault == NoFault) { + %(memacc_code)s; + } + + if (fault == NoFault) { + Addr size = 64; + EA &= ~(size - 1); + fault = xc->writeMem(NULL, size, EA, memAccessFlags, NULL); + } + } else { + xc->setPredicate(false); + } + + return fault; + } +}}; + +def template Mcr15CompleteAcc {{ + Fault %(class_name)s::completeAcc(PacketPtr pkt, + ExecContext *xc, + Trace::InstRecord *traceData) const + { + return NoFault; + } +}}; -- cgit v1.2.3