void
DefaultCommit<Impl>::handleInterrupt()
{
- if (interrupt != NoFault) {
- // Wait until the ROB is empty and all stores have drained in
- // order to enter the interrupt.
- if (rob->isEmpty() && !iewStage->hasStoresToWB()) {
- // Squash or record that I need to squash this cycle if
- // an interrupt needed to be handled.
- DPRINTF(Commit, "Interrupt detected.\n");
+ // Verify that we still have an interrupt to handle
+ if (!cpu->checkInterrupts(cpu->tcBase(0))) {
+ DPRINTF(Commit, "Pending interrupt is cleared by master before "
+ "it got handled. Restart fetching from the orig path.\n");
+ toIEW->commitInfo[0].clearInterrupt = true;
+ interrupt = NoFault;
+ return;
+ }
- // Clear the interrupt now that it's going to be handled
- toIEW->commitInfo[0].clearInterrupt = true;
+ // Wait until the ROB is empty and all stores have drained in
+ // order to enter the interrupt.
+ if (rob->isEmpty() && !iewStage->hasStoresToWB()) {
+ // Squash or record that I need to squash this cycle if
+ // an interrupt needed to be handled.
+ DPRINTF(Commit, "Interrupt detected.\n");
- assert(!thread[0]->inSyscall);
- thread[0]->inSyscall = true;
+ // Clear the interrupt now that it's going to be handled
+ toIEW->commitInfo[0].clearInterrupt = true;
- // CPU will handle interrupt.
- cpu->processInterrupts(interrupt);
+ assert(!thread[0]->inSyscall);
+ thread[0]->inSyscall = true;
- thread[0]->inSyscall = false;
+ // CPU will handle interrupt.
+ cpu->processInterrupts(interrupt);
- commitStatus[0] = TrapPending;
+ thread[0]->inSyscall = false;
- // Generate trap squash event.
- generateTrapEvent(0);
+ commitStatus[0] = TrapPending;
- interrupt = NoFault;
- } else {
- DPRINTF(Commit, "Interrupt pending, waiting for ROB to empty.\n");
- }
- } else if (commitStatus[0] != TrapPending &&
- cpu->checkInterrupts(cpu->tcBase(0)) &&
- !trapSquash[0] &&
- !tcSquash[0]) {
- // Process interrupts if interrupts are enabled, not in PAL
- // mode, and no other traps or external squashes are currently
- // pending.
- // @todo: Allow other threads to handle interrupts.
-
- // Get any interrupt that happened
- interrupt = cpu->getInterrupts();
-
- if (interrupt != NoFault) {
- // Tell fetch that there is an interrupt pending. This
- // will make fetch wait until it sees a non PAL-mode PC,
- // at which point it stops fetching instructions.
- toIEW->commitInfo[0].interruptPending = true;
- }
+ // Generate trap squash event.
+ generateTrapEvent(0);
+
+ interrupt = NoFault;
+ } else {
+ DPRINTF(Commit, "Interrupt pending, waiting for ROB to empty.\n");
}
}
+
+template <class Impl>
+void
+DefaultCommit<Impl>::propagateInterrupt()
+{
+ if (commitStatus[0] == TrapPending || interrupt || trapSquash[0] ||
+ tcSquash[0])
+ return;
+
+ // Process interrupts if interrupts are enabled, not in PAL
+ // mode, and no other traps or external squashes are currently
+ // pending.
+ // @todo: Allow other threads to handle interrupts.
+
+ // Get any interrupt that happened
+ interrupt = cpu->getInterrupts();
+
+ // Tell fetch that there is an interrupt pending. This
+ // will make fetch wait until it sees a non PAL-mode PC,
+ // at which point it stops fetching instructions.
+ if (interrupt != NoFault)
+ toIEW->commitInfo[0].interruptPending = true;
+}
+
#endif // FULL_SYSTEM
template <class Impl>
{
#if FULL_SYSTEM
- // Check for any interrupt, and start processing it. Or if we
- // have an outstanding interrupt and are at a point when it is
- // valid to take an interrupt, process it.
- if (cpu->checkInterrupts(cpu->tcBase(0))) {
+ // Check for any interrupt that we've already squashed for and start processing it.
+ if (interrupt != NoFault)
handleInterrupt();
- }
+
+ // Check if we have a interrupt and get read to handle it
+ if (cpu->checkInterrupts(cpu->tcBase(0)))
+ propagateInterrupt();
#endif // FULL_SYSTEM
////////////////////////////////////
/*
+ * Copyright (c) 2010 ARM Limited
+ * All rights reserved.
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder. You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
* Copyright (c) 2004-2006 The Regents of The University of Michigan
* All rights reserved.
*
DPRINTF(Fetch, "[tid:%i] Can't fetch cache line, switched out\n",
tid);
return false;
- } else if (interruptPending && !(pc & 0x3)) {
+ } else if (checkInterrupt(pc)) {
// Hold off fetch from getting new instructions when:
// Cache is blocked, or
// while an interrupt is pending and we're not in PAL mode, or
fetchStatus[tid] = TrapPending;
status_change = true;
- DPRINTF(Fetch, "[tid:%i]: fault (%s) detected @ PC %s",
- tid, fault->name(), thisPC);
+ DPRINTF(Fetch, "[tid:%i]: fault (%s) detected @ PC %s, sending nop "
+ "[sn:%lli]\n", tid, fault->name(), thisPC, inst_seq);
}
}