"registers from main CPU", curTick(), unverifiedInst->instAddr());
// Terribly convoluted way to make sure O3 model does not implode
- bool inSyscall = unverifiedInst->thread->inSyscall;
- unverifiedInst->thread->inSyscall = true;
+ bool no_squash_from_TC = unverifiedInst->thread->noSquashFromTC;
+ unverifiedInst->thread->noSquashFromTC = true;
// Heavy-weight copying of all registers
thread->copyArchRegs(unverifiedInst->tcBase());
- unverifiedInst->thread->inSyscall = inSyscall;
+ unverifiedInst->thread->noSquashFromTC = no_squash_from_TC;
// Set curStaticInst to unverifiedInst->staticInst
curStaticInst = unverifiedInst->staticInst;
BaseCPU::init();
for (ThreadID tid = 0; tid < numThreads; ++tid) {
- // Set inSyscall so that the CPU doesn't squash when initially
+ // Set noSquashFromTC so that the CPU doesn't squash when initially
// setting up registers.
- thread[tid]->inSyscall = true;
+ thread[tid]->noSquashFromTC = true;
// Initialise the ThreadContext's memory proxies
thread[tid]->initMemProxies(thread[tid]->getTC());
}
}
}
- // Clear inSyscall.
+ // Clear noSquashFromTC.
for (ThreadID tid = 0; tid < numThreads; ++tid)
- thread[tid]->inSyscall = false;
+ thread[tid]->noSquashFromTC = false;
// Call Initializiation Routine for Resource Pool
resPool->init();
// when using the TC during an instruction's execution
// (specifically for instructions that have side-effects that use
// the TC). Fix this.
- bool in_syscall = this->thread->inSyscall;
- this->thread->inSyscall = true;
+ bool no_squash_from_TC = this->thread->noSquashFromTC;
+ this->thread->noSquashFromTC = true;
this->fault = this->staticInst->execute(this, this->traceData);
- this->thread->inSyscall = in_syscall;
+ this->thread->noSquashFromTC = no_squash_from_TC;
return this->fault;
}
// when using the TC during an instruction's execution
// (specifically for instructions that have side-effects that use
// the TC). Fix this.
- bool in_syscall = this->thread->inSyscall;
- this->thread->inSyscall = true;
+ bool no_squash_from_TC = this->thread->noSquashFromTC;
+ this->thread->noSquashFromTC = true;
this->fault = this->staticInst->initiateAcc(this, this->traceData);
- this->thread->inSyscall = in_syscall;
+ this->thread->noSquashFromTC = no_squash_from_TC;
return this->fault;
}
copyArchRegs(old_context);
thread->funcExeInst = old_context->readFuncExeInst();
-
+
old_context->setStatus(ThreadContext::Halted);
- thread->inSyscall = false;
+ thread->noSquashFromTC = false;
thread->trapPending = false;
}
void
InOrderThreadContext::unserialize(Checkpoint *cp, const std::string §ion)
{
- panic("unserialize unimplemented");
+ panic("unserialize unimplemented");
}
InOrderCPU *cpu;
public:
- /** Whether or not the thread is currently in syscall mode, and
- * thus able to be externally updated without squashing.
+ /* This variable controls if writes to a thread context should cause a all
+ * dynamic/speculative state to be thrown away. Nominally this is the
+ * desired behavior because the external thread context write has updated
+ * some state that could be used by an inflight instruction, however there
+ * are some cases like in a fault/trap handler where this behavior would
+ * lead to successive restarts and forward progress couldn't be made. This
+ * variable controls if the squashing will occur.
*/
- bool inSyscall;
+ bool noSquashFromTC;
/** Whether or not the thread is currently waiting on a trap, and
* thus able to be externally updated without squashing.
Process *_process)
: ThreadState(reinterpret_cast<BaseCPU*>(_cpu), _thread_num,
_process),
- cpu(_cpu), inSyscall(0), trapPending(0), lastGradIsBranch(false)
+ cpu(_cpu), noSquashFromTC(false), trapPending(false),
+ lastGradIsBranch(false)
{ }
/** Handles the syscall. */
DPRINTF(Commit, "Squashing from trap, restarting at PC %s\n", pc[tid]);
thread[tid]->trapPending = false;
- thread[tid]->inSyscall = false;
+ thread[tid]->noSquashFromTC = false;
trapInFlight[tid] = false;
trapSquash[tid] = false;
DPRINTF(Commit, "Squashing from TC, restarting at PC %s\n", pc[tid]);
- thread[tid]->inSyscall = false;
+ thread[tid]->noSquashFromTC = false;
assert(!thread[tid]->trapPending);
commitStatus[tid] = ROBSquashing;
// Clear the interrupt now that it's going to be handled
toIEW->commitInfo[0].clearInterrupt = true;
- assert(!thread[0]->inSyscall);
- thread[0]->inSyscall = true;
+ assert(!thread[0]->noSquashFromTC);
+ thread[0]->noSquashFromTC = true;
if (cpu->checker) {
cpu->checker->handlePendingInt();
// CPU will handle interrupt.
cpu->processInterrupts(interrupt);
- thread[0]->inSyscall = false;
+ thread[0]->noSquashFromTC = false;
commitStatus[0] = TrapPending;
Addr oldpc;
// Debug statement. Checks to make sure we're not
// currently updating state while handling PC events.
- assert(!thread[tid]->inSyscall && !thread[tid]->trapPending);
+ assert(!thread[tid]->noSquashFromTC && !thread[tid]->trapPending);
do {
oldpc = pc[tid].instAddr();
cpu->system->pcEventQueue.service(thread[tid]->getTC());
cpu->checker->verify(head_inst);
}
- assert(!thread[tid]->inSyscall);
+ assert(!thread[tid]->noSquashFromTC);
// Mark that we're in state update mode so that the trap's
// execution doesn't generate extra squashes.
- thread[tid]->inSyscall = true;
+ thread[tid]->noSquashFromTC = true;
// Execute the trap. Although it's slightly unrealistic in
// terms of timing (as it doesn't wait for the full timing of
cpu->trap(inst_fault, tid, head_inst->staticInst);
// Exit state update mode to avoid accidental updating.
- thread[tid]->inSyscall = false;
+ thread[tid]->noSquashFromTC = false;
commitStatus[tid] = TrapPending;
BaseCPU::init();
for (ThreadID tid = 0; tid < numThreads; ++tid) {
- // Set inSyscall so that the CPU doesn't squash when initially
+ // Set noSquashFromTC so that the CPU doesn't squash when initially
// setting up registers.
- thread[tid]->inSyscall = true;
+ thread[tid]->noSquashFromTC = true;
// Initialise the ThreadContext's memory proxies
thread[tid]->initMemProxies(thread[tid]->getTC());
}
}
}
- // Clear inSyscall.
+ // Clear noSquashFromTC.
for (int tid = 0; tid < numThreads; ++tid)
- thread[tid]->inSyscall = false;
+ thread[tid]->noSquashFromTC = false;
// Initialize stages.
fetch.initStage();
void
FullO3CPU<Impl>::squashFromTC(ThreadID tid)
{
- this->thread[tid]->inSyscall = true;
+ this->thread[tid]->noSquashFromTC = true;
this->commit.generateTCEvent(tid);
}
// using the TC during an instruction's execution (specifically for
// instructions that have side-effects that use the TC). Fix this.
// See cpu/o3/dyn_inst_impl.hh.
- bool in_syscall = this->thread->inSyscall;
- this->thread->inSyscall = true;
+ bool no_squash_from_TC = this->thread->noSquashFromTC;
+ this->thread->noSquashFromTC = true;
for (int i = 0; i < _numDestMiscRegs; i++)
this->cpu->setMiscReg(
_destMiscRegIdx[i], _destMiscRegVal[i], this->threadNumber);
- this->thread->inSyscall = in_syscall;
+ this->thread->noSquashFromTC = no_squash_from_TC;
}
void forwardOldRegs()
// when using the TC during an instruction's execution
// (specifically for instructions that have side-effects that use
// the TC). Fix this.
- bool in_syscall = this->thread->inSyscall;
- this->thread->inSyscall = true;
+ bool no_squash_from_TC = this->thread->noSquashFromTC;
+ this->thread->noSquashFromTC = true;
this->fault = this->staticInst->execute(this, this->traceData);
- this->thread->inSyscall = in_syscall;
+ this->thread->noSquashFromTC = no_squash_from_TC;
return this->fault;
}
// when using the TC during an instruction's execution
// (specifically for instructions that have side-effects that use
// the TC). Fix this.
- bool in_syscall = this->thread->inSyscall;
- this->thread->inSyscall = true;
+ bool no_squash_from_TC = this->thread->noSquashFromTC;
+ this->thread->noSquashFromTC = true;
this->fault = this->staticInst->initiateAcc(this, this->traceData);
- this->thread->inSyscall = in_syscall;
+ this->thread->noSquashFromTC = no_squash_from_TC;
return this->fault;
}
// when using the TC during an instruction's execution
// (specifically for instructions that have side-effects that use
// the TC). Fix this.
- bool in_syscall = this->thread->inSyscall;
- this->thread->inSyscall = true;
+ bool no_squash_from_TC = this->thread->noSquashFromTC;
+ this->thread->noSquashFromTC = true;
if (this->cpu->checker) {
if (this->isStoreConditional()) {
this->fault = this->staticInst->completeAcc(pkt, this, this->traceData);
- this->thread->inSyscall = in_syscall;
+ this->thread->noSquashFromTC = no_squash_from_TC;
return this->fault;
}
{
return this->thread->quiesceEvent;
}
+ /** check if the cpu is currently in state update mode and squash if not.
+ * This function will return true if a trap is pending or if a fault or
+ * similar is currently writing to the thread context and doesn't want
+ * reset all the state (see noSquashFromTC).
+ */
+ inline void conditionalSquash()
+ {
+ if (!thread->trapPending && !thread->noSquashFromTC)
+ cpu->squashFromTC(thread->threadId());
+ }
};
old_context->setStatus(ThreadContext::Halted);
- thread->inSyscall = false;
+ thread->noSquashFromTC = false;
thread->trapPending = false;
}
O3ThreadContext<Impl>::copyArchRegs(ThreadContext *tc)
{
// Prevent squashing
- thread->inSyscall = true;
+ thread->noSquashFromTC = true;
TheISA::copyRegs(tc, this);
- thread->inSyscall = false;
+ thread->noSquashFromTC = false;
if (!FullSystem)
this->thread->funcExeInst = tc->readFuncExeInst();
reg_idx = cpu->isa[thread->threadId()].flattenIntIndex(reg_idx);
cpu->setArchIntReg(reg_idx, val, thread->threadId());
- // Squash if we're not already in a state update mode.
- if (!thread->trapPending && !thread->inSyscall) {
- cpu->squashFromTC(thread->threadId());
- }
+ conditionalSquash();
}
template <class Impl>
reg_idx = cpu->isa[thread->threadId()].flattenFloatIndex(reg_idx);
cpu->setArchFloatReg(reg_idx, val, thread->threadId());
- if (!thread->trapPending && !thread->inSyscall) {
- cpu->squashFromTC(thread->threadId());
- }
+ conditionalSquash();
}
template <class Impl>
reg_idx = cpu->isa[thread->threadId()].flattenFloatIndex(reg_idx);
cpu->setArchFloatRegInt(reg_idx, val, thread->threadId());
- // Squash if we're not already in a state update mode.
- if (!thread->trapPending && !thread->inSyscall) {
- cpu->squashFromTC(thread->threadId());
- }
+ conditionalSquash();
}
template <class Impl>
{
cpu->pcState(val, thread->threadId());
- // Squash if we're not already in a state update mode.
- if (!thread->trapPending && !thread->inSyscall) {
- cpu->squashFromTC(thread->threadId());
- }
+ conditionalSquash();
}
template <class Impl>
{
cpu->pcState(val, thread->threadId());
- // Squash if we're not already in a state update mode.
- if (!thread->trapPending && !thread->inSyscall) {
- cpu->squashFromTC(thread->threadId());
- }
+ conditionalSquash();
}
template <class Impl>
{
cpu->setMiscRegNoEffect(misc_reg, val, thread->threadId());
- // Squash if we're not already in a state update mode.
- if (!thread->trapPending && !thread->inSyscall) {
- cpu->squashFromTC(thread->threadId());
- }
+ conditionalSquash();
}
template <class Impl>
{
cpu->setMiscReg(misc_reg, val, thread->threadId());
- // Squash if we're not already in a state update mode.
- if (!thread->trapPending && !thread->inSyscall) {
- cpu->squashFromTC(thread->threadId());
- }
+ conditionalSquash();
}
/** Pointer to the CPU. */
O3CPU *cpu;
public:
- /** Whether or not the thread is currently in syscall mode, and
- * thus able to be externally updated without squashing.
+ /* This variable controls if writes to a thread context should cause a all
+ * dynamic/speculative state to be thrown away. Nominally this is the
+ * desired behavior because the external thread context write has updated
+ * some state that could be used by an inflight instruction, however there
+ * are some cases like in a fault/trap handler where this behavior would
+ * lead to successive restarts and forward progress couldn't be made. This
+ * variable controls if the squashing will occur.
*/
- bool inSyscall;
+ bool noSquashFromTC;
/** Whether or not the thread is currently waiting on a trap, and
* thus able to be externally updated without squashing.
O3ThreadState(O3CPU *_cpu, int _thread_num, Process *_process)
: ThreadState(_cpu, _thread_num, _process),
- cpu(_cpu), inSyscall(0), trapPending(0)
+ cpu(_cpu), noSquashFromTC(false), trapPending(false)
{
if (!FullSystem)
return;
DPRINTF(BE, "Inst [sn:%lli] PC %#x has a fault\n",
inst->seqNum, inst->readPC());
-// assert(!thread->inSyscall);
+// assert(!thread->noSquashFromTC);
-// thread->inSyscall = true;
+// thread->noSquashFromTC = true;
// Consider holding onto the trap and waiting until the trap event
// happens for this to be executed.
inst_fault->invoke(thread->getXCProxy());
// Exit state update mode to avoid accidental updating.
-// thread->inSyscall = false;
+// thread->noSquashFromTC = false;
// commitStatus = TrapPending;
Addr oldpc;
do {
if (count == 0)
- assert(!thread->inSyscall && !thread->trapPending);
+ assert(!thread->noSquashFromTC && !thread->trapPending);
oldpc = thread->readPC();
cpu->system->pcEventQueue.service(
thread->getXCProxy());
ozoneTC.cpu = this;
ozoneTC.thread = &thread;
- thread.inSyscall = false;
+ thread.noSquashFromTC = false;
itb = p->itb;
dtb = p->dtb;
BaseCPU::takeOverFrom(oldCPU);
thread.trapPending = false;
- thread.inSyscall = false;
+ thread.noSquashFromTC = false;
backEnd->takeOverFrom();
frontEnd->takeOverFrom();
BaseCPU::init();
// Mark this as in syscall so it won't need to squash
- thread.inSyscall = true;
+ thread.noSquashFromTC = true;
if (FullSystem) {
for (int i = 0; i < threadContexts.size(); ++i) {
ThreadContext *tc = threadContexts[i];
frontEnd->renameTable.copyFrom(thread.renameTable);
backEnd->renameTable.copyFrom(thread.renameTable);
- thread.inSyscall = false;
+ thread.noSquashFromTC = false;
}
template <class Impl>
void
OzoneCPU<Impl>::squashFromTC()
{
- thread.inSyscall = true;
+ thread.noSquashFromTC = true;
backEnd->generateTCEvent();
}
// Not sure this copy is needed, depending on how the TC proxy is made.
thread.renameTable.copyFrom(backEnd->renameTable);
- thread.inSyscall = true;
+ thread.noSquashFromTC = true;
thread.funcExeInst++;
thread.funcExeInst--;
- thread.inSyscall = false;
+ thread.noSquashFromTC = false;
frontEnd->renameTable.copyFrom(thread.renameTable);
backEnd->renameTable.copyFrom(thread.renameTable);
{
thread->renameTable[reg_idx]->setIntResult(val);
- if (!thread->inSyscall) {
+ if (!thread->noSquashFromTC) {
cpu->squashFromTC();
}
}
thread->renameTable[idx]->setDoubleResult(val);
- if (!thread->inSyscall) {
+ if (!thread->noSquashFromTC) {
cpu->squashFromTC();
}
}
thread->PC = val;
cpu->frontEnd->setPC(val);
- if (!thread->inSyscall) {
+ if (!thread->noSquashFromTC) {
cpu->squashFromTC();
}
}
thread->nextPC = val;
cpu->frontEnd->setNextPC(val);
- if (!thread->inSyscall) {
+ if (!thread->noSquashFromTC) {
cpu->squashFromTC();
}
}
// Needs to setup a squash event unless we're in syscall mode
thread->miscRegFile.setRegNoEffect(misc_reg, val);
- if (!thread->inSyscall) {
+ if (!thread->noSquashFromTC) {
cpu->squashFromTC();
}
}
// Needs to setup a squash event unless we're in syscall mode
thread->miscRegFile.setReg(misc_reg, val, this);
- if (!thread->inSyscall) {
+ if (!thread->noSquashFromTC) {
cpu->squashFromTC();
}
}
// @todo: Pretty convoluted way to avoid squashing from happening when using
// the XC during an instruction's execution (specifically for instructions
// that have sideeffects that use the XC). Fix this.
- bool in_syscall = this->thread->inSyscall;
- this->thread->inSyscall = true;
+ bool no_squash_from_TC = this->thread->noSquashFromTC;
+ this->thread->noSquashFromTC = true;
this->fault = this->staticInst->execute(this, this->traceData);
- this->thread->inSyscall = in_syscall;
+ this->thread->noSquashFromTC = no_squash_from_TC;
return this->fault;
}
// @todo: Pretty convoluted way to avoid squashing from happening when using
// the XC during an instruction's execution (specifically for instructions
// that have sideeffects that use the XC). Fix this.
- bool in_syscall = this->thread->inSyscall;
- this->thread->inSyscall = true;
+ bool no_squash_from_TC = this->thread->noSquashFromTC;
+ this->thread->noSquashFromTC = true;
this->fault = this->staticInst->initiateAcc(this, this->traceData);
- this->thread->inSyscall = in_syscall;
+ this->thread->noSquashFromTC = no_squash_from_TC;
return this->fault;
}
}
if (ipl && ipl > thread->readMiscRegNoEffect(IPR_IPLR)) {
- thread->inSyscall = true;
+ thread->noSquashFromTC = true;
thread->setMiscRegNoEffect(IPR_ISR, summary);
thread->setMiscRegNoEffect(IPR_INTID, ipl);
// May need to go 1 inst prior
squashPending = true;
- thread->inSyscall = false;
+ thread->noSquashFromTC = false;
setSquashInfoFromXC();
}
Addr oldpc;
do {
if (count == 0)
- assert(!thread->inSyscall && !thread->trapPending);
+ assert(!thread->noSquashFromTC && !thread->trapPending);
oldpc = thread->readPC();
cpu->system->pcEventQueue.service(
thread->getXCProxy());
DPRINTF(IBE, "Inst [sn:%lli] PC %#x has a fault\n",
inst->seqNum, inst->readPC());
- assert(!thread->inSyscall);
+ assert(!thread->noSquashFromTC);
- thread->inSyscall = true;
+ thread->noSquashFromTC = true;
// Consider holding onto the trap and waiting until the trap event
// happens for this to be executed.
inst_fault->invoke(xc);
// Exit state update mode to avoid accidental updating.
- thread->inSyscall = false;
+ thread->noSquashFromTC = false;
squashPending = true;
{
DPRINTF(Commit, "Handling fault from fetch\n");
- assert(!thread->inSyscall);
+ assert(!thread->noSquashFromTC);
- thread->inSyscall = true;
+ thread->noSquashFromTC = true;
// Consider holding onto the trap and waiting until the trap event
// happens for this to be executed.
faultFromFetch->invoke(xc);
// Exit state update mode to avoid accidental updating.
- thread->inSyscall = false;
+ thread->noSquashFromTC = false;
squashPending = true;
squashPending = false;
// Probably want to make sure that this squash is the one that set the
- // thread into inSyscall mode.
- thread->inSyscall = false;
+ // thread into noSquashFromTC mode.
+ thread->noSquashFromTC = false;
// Tell front end to squash, reset PC to new one.
frontEnd->squash(squash_num, next_PC);
// Record that I need to squash
squashPending = true;
- thread->inSyscall = true;
+ thread->noSquashFromTC = true;
}
template <class Impl>
// Not sure which thread should be the one to interrupt. For now
// always do thread 0.
- assert(!thread->inSyscall);
- thread->inSyscall = true;
+ assert(!thread->noSquashFromTC);
+ thread->noSquashFromTC = true;
// CPU will handle implementation of the interrupt.
cpu->processInterrupts();
commitStatus = TrapPending;
// Exit state update mode to avoid accidental updating.
- thread->inSyscall = false;
+ thread->noSquashFromTC = false;
// Generate trap squash event.
generateTrapEvent();
{
DPRINTF(BE, "Handling fault!\n");
- assert(!thread->inSyscall);
+ assert(!thread->noSquashFromTC);
- thread->inSyscall = true;
+ thread->noSquashFromTC = true;
// Consider holding onto the trap and waiting until the trap event
// happens for this to be executed.
fault->invoke(thread->getTC());
// Exit state update mode to avoid accidental updating.
- thread->inSyscall = false;
+ thread->noSquashFromTC = false;
commitStatus = TrapPending;
Addr oldpc;
do {
if (count == 0)
- assert(!thread->inSyscall && !thread->trapPending);
+ assert(!thread->noSquashFromTC && !thread->trapPending);
oldpc = thread->readPC();
cpu->system->pcEventQueue.service(
thread->getTC());
frontEnd->interruptPending = false;
thread->trapPending = false;
- thread->inSyscall = false;
+ thread->noSquashFromTC = false;
tcSquash = false;
commitStatus = Running;
}
frontEnd->interruptPending = false;
thread->trapPending = false;
- thread->inSyscall = false;
+ thread->noSquashFromTC = false;
trapSquash = false;
commitStatus = Running;
}
OzoneThreadState(CPUType *_cpu, int _thread_num)
: ThreadState(_cpu, -1, _thread_num),
- intrflag(0), cpu(_cpu), inSyscall(0), trapPending(0)
+ intrflag(0), cpu(_cpu), noSquashFromTC(false), trapPending(false)
{
if (cpu->params->profile) {
profile = new FunctionProfile(cpu->params->system->kernelSymtab);
OzoneThreadState(CPUType *_cpu, int _thread_num, Process *_process)
: ThreadState(_cpu, -1, _thread_num, _process),
- cpu(_cpu), inSyscall(0), trapPending(0)
+ cpu(_cpu), noSquashFromTC(false), trapPending(false)
{
miscRegFile.clear();
}
typename Impl::CPUType *cpu;
- bool inSyscall;
+ bool noSquashFromTC;
bool trapPending;