arm: Add support for the mcr dc{ic,i,c}mvac, dccmvau instructions
authorNikos Nikoleris <nikos.nikoleris@arm.com>
Tue, 7 Feb 2017 11:35:10 +0000 (11:35 +0000)
committerNikos Nikoleris <nikos.nikoleris@arm.com>
Tue, 5 Dec 2017 11:47:01 +0000 (11:47 +0000)
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 <stephan.diestelhorst@arm.com>
Reviewed-by: Anouk Van Laer <anouk.vanlaer@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/5059
Maintainer: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-by: Jason Lowe-Power <jason@lowepower.com>
src/arch/arm/insts/misc.cc
src/arch/arm/insts/misc.hh
src/arch/arm/isa/formats/misc.isa
src/arch/arm/isa/insts/misc.isa
src/arch/arm/isa/templates/misc.isa

index ec1b9358c3cbb554dcb5ec6a4211ed7ef6e2931f..ba97eff091698504fd9d7ffb24a14b670fc95489 100644 (file)
@@ -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
 {
index c2dcaa8474c581ab58e5ef46699c21ca91824b96..72d1694c9389638a15f20fd316b7ade1174d6231 100644 (file)
@@ -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:
index 26681e40f030e5ed4c937be046df3e4a1adf2e3b..4f834b8e1a40459cbd3edde1d098296b94bcac00 100644 (file)
@@ -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",
index 80ad6cdf42566ab9bb519b1476c8c68511efbf50..ef0a6709ed9d4774c8d6acbd2a5be62349a90d17 100644 (file)
@@ -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<UndefinedInstruction>(machInst, false,
+                                                          mnemonic);
+        }
+        if (hypTrap) {
+            return std::make_shared<HypervisorTrap>(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,
index 0a23ba5d32d3bcc4f16bf0143e644c0235e132ee..639ff3acae219188989aeee8982f58f4619ec8d6 100644 (file)
@@ -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;
+    }
+}};