changeset 9c87727099ce in /z/repo/gem5
details: http://repo.gem5.org/gem5?cmd=changeset;node=9c87727099ce
description:
        Fix bugs due to interaction between SEV instructions and O3 pipeline

        SEV instructions were originally implemented to cause asynchronous 
squashes
        via the generateTCSquash() function in the O3 pipeline when updating the
        SEV_MAILBOX miscReg. This caused race conditions between CPUs in an MP 
system
        that would lead to a pipeline either going inactive indefinitely or not 
being
        able to commit squashed instructions. Fixed SEV instructions to behave 
like
        interrupts and cause synchronous sqaushes inside the pipeline, 
eliminating
        the race conditions. Also fixed up the semantics of the WFE instruction 
to
        behave as documented in the ARMv7 ISA description to not sleep if 
SEV_MAILBOX=1
        or unmasked interrupts are pending.

diffstat:

 src/arch/arm/faults.cc              |  16 ++++++++++++++++
 src/arch/arm/faults.hh              |   9 +++++++++
 src/arch/arm/interrupts.hh          |   5 ++++-
 src/arch/arm/isa/insts/misc.isa     |  25 +++++++++++++++++++------
 src/arch/arm/isa/templates/pred.isa |  28 ++++++++++++++++++++++++++++
 src/arch/arm/isa_traits.hh          |   1 +
 src/cpu/o3/commit_impl.hh           |   1 +
 src/cpu/o3/cpu.hh                   |  16 +++++++++++++---
 src/cpu/o3/thread_context_impl.hh   |   3 +--
 9 files changed, 92 insertions(+), 12 deletions(-)

diffs (243 lines):

diff -r 684ea9e5cd96 -r 9c87727099ce src/arch/arm/faults.cc
--- a/src/arch/arm/faults.cc    Fri Aug 19 15:08:06 2011 -0500
+++ b/src/arch/arm/faults.cc    Fri Aug 19 15:08:07 2011 -0500
@@ -78,6 +78,8 @@
 template<> ArmFault::FaultVals ArmFaultVals<ReExec>::vals =
     {"ReExec Flush", 0x00, MODE_SVC, 0, 0, true, true}; // some dummy values
 
+template<> ArmFault::FaultVals ArmFaultVals<ArmSev>::vals =
+    {"ArmSev Flush", 0x00, MODE_SVC, 0, 0, true, true}; // some dummy values
 Addr 
 ArmFault::getVector(ThreadContext *tc)
 {
@@ -127,6 +129,8 @@
     cpsr.i = 1;
     cpsr.e = sctlr.ee;
     tc->setMiscReg(MISCREG_CPSR, cpsr);
+    // Make sure mailbox sets to one always
+    tc->setMiscReg(MISCREG_SEV_MAILBOX, 1);
     tc->setIntReg(INTREG_LR, curPc +
             (saved_cpsr.t ? thumbPcOffset() : armPcOffset()));
 
@@ -252,6 +256,18 @@
 template void AbortFault<DataAbort>::invoke(ThreadContext *tc,
                                             StaticInstPtr inst);
 
+void
+ArmSev::invoke(ThreadContext *tc, StaticInstPtr inst) {
+    DPRINTF(Faults, "Invoking ArmSev Fault\n");
+#if FULL_SYSTEM
+    // Set sev_mailbox to 1, clear the pending interrupt from remote
+    // SEV execution and let pipeline continue as pcState is still
+    // valid.
+    tc->setMiscReg(MISCREG_SEV_MAILBOX, 1);
+    tc->getCpuPtr()->clearInterrupt(INT_SEV, 0);
+#endif
+}
+
 // return via SUBS pc, lr, xxx; rfe, movs, ldm
 
 } // namespace ArmISA
diff -r 684ea9e5cd96 -r 9c87727099ce src/arch/arm/faults.hh
--- a/src/arch/arm/faults.hh    Fri Aug 19 15:08:06 2011 -0500
+++ b/src/arch/arm/faults.hh    Fri Aug 19 15:08:07 2011 -0500
@@ -257,6 +257,15 @@
     return new Reset();
 }
 
+// A fault that flushes the pipe, excluding the faulting instructions
+class ArmSev : public ArmFaultVals<ArmSev>
+{
+  public:
+    ArmSev () {}
+    void invoke(ThreadContext *tc,
+            StaticInstPtr inst = StaticInst::nullStaticInstPtr);
+};
+
 } // namespace ArmISA
 
 #endif // __ARM_FAULTS_HH__
diff -r 684ea9e5cd96 -r 9c87727099ce src/arch/arm/interrupts.hh
--- a/src/arch/arm/interrupts.hh        Fri Aug 19 15:08:06 2011 -0500
+++ b/src/arch/arm/interrupts.hh        Fri Aug 19 15:08:07 2011 -0500
@@ -134,7 +134,8 @@
         return ((interrupts[INT_IRQ] && !cpsr.i) ||
                 (interrupts[INT_FIQ] && !cpsr.f) ||
                 (interrupts[INT_ABT] && !cpsr.a) ||
-                (interrupts[INT_RST]));
+                (interrupts[INT_RST]) ||
+                (interrupts[INT_SEV]));
     }
 
     /**
@@ -167,6 +168,8 @@
                     ArmFault::AsynchronousExternalAbort);
         if (interrupts[INT_RST])
            return new Reset;
+        if (interrupts[INT_SEV])
+           return new ArmSev;
 
         panic("intStatus and interrupts not in sync\n");
     }
diff -r 684ea9e5cd96 -r 9c87727099ce src/arch/arm/isa/insts/misc.isa
--- a/src/arch/arm/isa/insts/misc.isa   Fri Aug 19 15:08:06 2011 -0500
+++ b/src/arch/arm/isa/insts/misc.isa   Fri Aug 19 15:08:07 2011 -0500
@@ -502,20 +502,32 @@
 
     wfeCode = '''
 #if FULL_SYSTEM
+    // WFE Sleeps if SevMailbox==0 and no unmasked interrupts are pending
     if (SevMailbox == 1) {
         SevMailbox = 0;
         PseudoInst::quiesceSkip(xc->tcBase());
+    } else if 
(xc->tcBase()->getCpuPtr()->getInterruptController()->checkInterrupts(xc->tcBase()))
 {
+        PseudoInst::quiesceSkip(xc->tcBase());
     } else {
         PseudoInst::quiesce(xc->tcBase());
     }
 #endif
     '''
+    wfePredFixUpCode = '''
+#if FULL_SYSTEM
+    // WFE is predicated false, reset SevMailbox to reduce spurious sleeps
+    // and SEV interrupts
+    SevMailbox = 1;
+#endif
+    '''
     wfeIop = InstObjParams("wfe", "WfeInst", "PredOp", \
-            { "code" : wfeCode, "predicate_test" : predicateTest },
+            { "code" : wfeCode,
+              "pred_fixup" : wfePredFixUpCode,
+              "predicate_test" : predicateTest },
             ["IsNonSpeculative", "IsQuiesce", "IsSerializeAfter"])
     header_output += BasicDeclare.subst(wfeIop)
     decoder_output += BasicConstructor.subst(wfeIop)
-    exec_output += QuiescePredOpExecute.subst(wfeIop)
+    exec_output += QuiescePredOpExecuteWithFixup.subst(wfeIop)
 
     wfiCode = '''
 #if FULL_SYSTEM
@@ -535,19 +547,20 @@
     exec_output += QuiescePredOpExecute.subst(wfiIop)
 
     sevCode = '''
-    // Need a way for O3 to not scoreboard these accesses as pipe flushes.
+#if FULL_SYSTEM
     SevMailbox = 1;
     System *sys = xc->tcBase()->getSystemPtr();
     for (int x = 0; x < sys->numContexts(); x++) {
         ThreadContext *oc = sys->getThreadContext(x);
         if (oc == xc->tcBase())
             continue;
-        // Only wake if they were sleeping
+        // Wake CPU with interrupt if they were sleeping
         if (oc->readMiscReg(MISCREG_SEV_MAILBOX) == 0) {
-            oc->setMiscReg(MISCREG_SEV_MAILBOX, 1);
-            PseudoInst::wakeCPU(xc->tcBase(), x);
+            // Post Interrupt and wake cpu if needed
+            oc->getCpuPtr()->postInterrupt(INT_SEV, 0);
         }
     }
+#endif
     '''
     sevIop = InstObjParams("sev", "SevInst", "PredOp", \
             { "code" : sevCode, "predicate_test" : predicateTest },
diff -r 684ea9e5cd96 -r 9c87727099ce src/arch/arm/isa/templates/pred.isa
--- a/src/arch/arm/isa/templates/pred.isa       Fri Aug 19 15:08:06 2011 -0500
+++ b/src/arch/arm/isa/templates/pred.isa       Fri Aug 19 15:08:07 2011 -0500
@@ -205,6 +205,34 @@
     }
 }};
 
+def template QuiescePredOpExecuteWithFixup {{
+    Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord 
*traceData) const
+    {
+        Fault fault = NoFault;
+        uint64_t resTemp = 0;
+        resTemp = resTemp;
+        %(op_decl)s;
+        %(op_rd)s;
+
+        if (%(predicate_test)s)
+        {
+            %(code)s;
+            if (fault == NoFault)
+            {
+                %(op_wb)s;
+            }
+        } else {
+            xc->setPredicate(false);
+            %(pred_fixup)s;
+#if FULL_SYSTEM
+            PseudoInst::quiesceSkip(xc->tcBase());
+#endif
+        }
+
+        return fault;
+    }
+}};
+
 def template DataDecode {{
     if (machInst.opcode4 == 0) {
         if (machInst.sField == 0)
diff -r 684ea9e5cd96 -r 9c87727099ce src/arch/arm/isa_traits.hh
--- a/src/arch/arm/isa_traits.hh        Fri Aug 19 15:08:06 2011 -0500
+++ b/src/arch/arm/isa_traits.hh        Fri Aug 19 15:08:07 2011 -0500
@@ -121,6 +121,7 @@
         INT_ABT,
         INT_IRQ,
         INT_FIQ,
+        INT_SEV, // Special interrupt for recieving SEV's
         NumInterruptTypes
     };
 } // namespace ArmISA
diff -r 684ea9e5cd96 -r 9c87727099ce src/cpu/o3/commit_impl.hh
--- a/src/cpu/o3/commit_impl.hh Fri Aug 19 15:08:06 2011 -0500
+++ b/src/cpu/o3/commit_impl.hh Fri Aug 19 15:08:07 2011 -0500
@@ -505,6 +505,7 @@
 
     cpu->schedule(trap, curTick() + trapLatency);
     trapInFlight[tid] = true;
+    thread[tid]->trapPending = true;
 }
 
 template <class Impl>
diff -r 684ea9e5cd96 -r 9c87727099ce src/cpu/o3/cpu.hh
--- a/src/cpu/o3/cpu.hh Fri Aug 19 15:08:06 2011 -0500
+++ b/src/cpu/o3/cpu.hh Fri Aug 19 15:08:07 2011 -0500
@@ -184,9 +184,19 @@
         if (activateThreadEvent[tid].squashed())
             reschedule(activateThreadEvent[tid],
                 nextCycle(curTick() + ticks(delay)));
-        else if (!activateThreadEvent[tid].scheduled())
-            schedule(activateThreadEvent[tid],
-                nextCycle(curTick() + ticks(delay)));
+        else if (!activateThreadEvent[tid].scheduled()) {
+            Tick when = nextCycle(curTick() + ticks(delay));
+
+            // Check if the deallocateEvent is also scheduled, and make
+            // sure they do not happen at same time causing a sleep that
+            // is never woken from.
+            if (deallocateContextEvent[tid].scheduled() &&
+                deallocateContextEvent[tid].when() == when) {
+                when++;
+            }
+
+            schedule(activateThreadEvent[tid], when);
+        }
     }
 
     /** Unschedule actiavte thread event, regardless of its current state. */
diff -r 684ea9e5cd96 -r 9c87727099ce src/cpu/o3/thread_context_impl.hh
--- a/src/cpu/o3/thread_context_impl.hh Fri Aug 19 15:08:06 2011 -0500
+++ b/src/cpu/o3/thread_context_impl.hh Fri Aug 19 15:08:07 2011 -0500
@@ -351,8 +351,7 @@
 
 template <class Impl>
 void
-O3ThreadContext<Impl>::setMiscReg(int misc_reg,
-                                                const MiscReg &val)
+O3ThreadContext<Impl>::setMiscReg(int misc_reg, const MiscReg &val)
 {
     cpu->setMiscReg(misc_reg, val, thread->threadId());
 
_______________________________________________
gem5-dev mailing list
[email protected]
http://m5sim.org/mailman/listinfo/gem5-dev

Reply via email to