diff options
author | Geoffrey Blake <geoffrey.blake@arm.com> | 2011-08-19 15:08:07 -0500 |
---|---|---|
committer | Geoffrey Blake <geoffrey.blake@arm.com> | 2011-08-19 15:08:07 -0500 |
commit | 5f425b8bd1ac70b61fc57b7ec44c52cd7d8de9fb (patch) | |
tree | decdd198675fc01637584a8ef65d50c216e992da /src/arch/arm/isa/insts | |
parent | f125ef22b997d5ba6173d9d3f0d07ae741e279bd (diff) | |
download | gem5-5f425b8bd1ac70b61fc57b7ec44c52cd7d8de9fb.tar.xz |
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 (limited to 'src/arch/arm/isa/insts')
-rw-r--r-- | src/arch/arm/isa/insts/misc.isa | 25 |
1 files changed, 19 insertions, 6 deletions
diff --git a/src/arch/arm/isa/insts/misc.isa b/src/arch/arm/isa/insts/misc.isa index 4a4f1e314..4d8ea66a2 100644 --- a/src/arch/arm/isa/insts/misc.isa +++ b/src/arch/arm/isa/insts/misc.isa @@ -502,20 +502,32 @@ let {{ 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 @@ let {{ 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 }, |