ARM: Adding a bogus fault that does nothing.
authorMin Kyu Jeong <minkyu.jeong@arm.com>
Thu, 26 Aug 2010 00:10:43 +0000 (19:10 -0500)
committerMin Kyu Jeong <minkyu.jeong@arm.com>
Thu, 26 Aug 2010 00:10:43 +0000 (19:10 -0500)
This fault can used to flush the pipe, not including the faulting instruction.

The particular case I needed this was for a self-modifying code. It needed to
drain the store queue and force the following instruction to refetch from
icache. DCCMVAC cp15 mcr instruction is modified to raise this fault.

src/arch/arm/faults.cc
src/arch/arm/faults.hh
src/arch/arm/isa/formats/misc.isa
src/arch/arm/isa/formats/unimp.isa

index 79973185d8a8d496568503b843614254554a32f6..2a6b7c359498db693eb3b0e408c4b4320ca6fc06 100644 (file)
@@ -71,6 +71,9 @@ template<> ArmFault::FaultVals ArmFaultVals<Interrupt>::vals =
 template<> ArmFault::FaultVals ArmFaultVals<FastInterrupt>::vals =
     {"FIQ", 0x1C, MODE_FIQ, 4, 4, true, true};
 
+template<> ArmFault::FaultVals ArmFaultVals<FlushPipe>::vals =
+    {"Pipe Flush", 0x00, MODE_SVC, 0, 0, true, true}; // some dummy values
+
 Addr 
 ArmFault::getVector(ThreadContext *tc)
 {
@@ -213,12 +216,22 @@ AbortFault<T>::invoke(ThreadContext *tc)
     tc->setMiscReg(T::FarIndex, faultAddr);
 }
 
+void
+FlushPipe::invoke(ThreadContext *tc) {
+    DPRINTF(Faults, "Invoking FlushPipe Fault\n");
+
+    // Set the PC to the next instruction of the faulting instruction.
+    // Net effect is simply squashing all instructions behind and
+    // start refetching from the next instruction.
+    tc->setPC(tc->readNextPC());
+    tc->setNextPC(tc->readNextNPC());
+    tc->setMicroPC(0);
+    tc->setNextMicroPC(1);
+}
+
 template void AbortFault<PrefetchAbort>::invoke(ThreadContext *tc);
 template void AbortFault<DataAbort>::invoke(ThreadContext *tc);
 
 // return via SUBS pc, lr, xxx; rfe, movs, ldm
 
-
-
 } // namespace ArmISA
-
index 7dd8814355a80aa7ab137ffe9be46051f322ae4f..3eef0e551766c8410b7bddd7e47f548a49bb8696 100644 (file)
@@ -227,6 +227,14 @@ class DataAbort : public AbortFault<DataAbort>
 class Interrupt : public ArmFaultVals<Interrupt> {};
 class FastInterrupt : public ArmFaultVals<FastInterrupt> {};
 
+// A fault that flushes the pipe, excluding the faulting instructions
+class FlushPipe : public ArmFaultVals<FlushPipe>
+{
+  public:
+    FlushPipe() {}
+    void invoke(ThreadContext *tc);
+};
+
 static inline Fault genMachineCheckFault()
 {
     return new Reset();
index 884d930667d5ff78b7c22b15337739ad288d3324..2d47c286ffca178b06a6e2d95d69ae832946568a 100644 (file)
@@ -111,7 +111,7 @@ let {{
             return new WarnUnimplemented(
                     isRead ? "mrc dcimvac" : "mcr dcimvac", machInst);
           case MISCREG_DCCMVAC:
-            return new WarnUnimplemented(
+            return new FlushPipeInst(
                     isRead ? "mrc dccmvac" : "mcr dccmvac", machInst);
           case MISCREG_DCCMVAU:
             return new WarnUnimplemented(
index a746f8a7b3f007b23aaec3cb0f7bb799cc013e18..a0e0afd32d3de4c4c06fa7131065db47d9a0b9ca 100644 (file)
@@ -101,6 +101,22 @@ output header {{
         std::string
         generateDisassembly(Addr pc, const SymbolTable *symtab) const;
     };
+
+    class FlushPipeInst : public ArmStaticInst
+    {
+      public:
+        FlushPipeInst(const char *_mnemonic, ExtMachInst _machInst)
+            : ArmStaticInst(_mnemonic, _machInst, No_OpClass)
+        {
+            flags[IsNonSpeculative] = true;
+        }
+
+        %(BasicExecDeclare)s
+
+        std::string
+        generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+
+    };
 }};
 
 output decoder {{
@@ -117,6 +133,13 @@ output decoder {{
     {
         return csprintf("%-10s (unimplemented)", mnemonic);
     }
+
+    std::string
+    FlushPipeInst::generateDisassembly(Addr pc,
+                                   const SymbolTable *symtab) const
+    {
+        return csprintf("%-10s (pipe flush)", mnemonic);
+    }
 }};
 
 output exec {{
@@ -142,6 +165,13 @@ output exec {{
 
         return NoFault;
     }
+
+    Fault
+    FlushPipeInst::execute(%(CPU_exec_context)s *xc,
+                           Trace::InstRecord *traceData) const
+    {
+        return new FlushPipe();
+    }
 }};