ARM: Use CPU local lock before sending load to mem system.
authorAli Saidi <Ali.Saidi@ARM.com>
Mon, 4 Apr 2011 16:42:29 +0000 (11:42 -0500)
committerAli Saidi <Ali.Saidi@ARM.com>
Mon, 4 Apr 2011 16:42:29 +0000 (11:42 -0500)
This change uses the locked_mem.hh header to handle implementing CLREX. It
simplifies the current implementation greatly.

src/arch/arm/isa/insts/misc.isa
src/arch/arm/isa/operands.isa
src/arch/arm/isa/templates/misc.isa
src/arch/arm/locked_mem.hh
src/arch/arm/miscregs.hh

index 35df88c813fb7a1909892638a2427c265ca2ede0..7333faef013ccd4ed692776e57bd0aaf8361b583 100644 (file)
@@ -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;
index 49a86021338aeaad5ca9dbbf1dd0b36c4cfc2b63..b497564b7d053bbbf40b93d6d70e2f872f2184c2 100644 (file)
@@ -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'),
index 694dc46da738067a81f635de0ff7f99bd2ac4e2d..212897aa09a365a91491dfe11388d7215f7e6ed9 100644 (file)
@@ -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;
-    }
-}};
-
index 41899273a31c14e17043e9877b8345c6ed073676..f902bdb49548c9817b8d21009c717f05a2474d9e 100644 (file)
@@ -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;
 }
 
index 2ccd9b4c2159950bba3bf1b4f494c8c00e4daf37..051cd490ea6d1238ddc4d8f76f748042f5c4e45b 100644 (file)
@@ -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",