summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGabe Black <gblack@eecs.umich.edu>2006-11-03 02:25:39 -0500
committerGabe Black <gblack@eecs.umich.edu>2006-11-03 02:25:39 -0500
commitc8fc116c7636893517254f785707eba1726d3265 (patch)
tree7d3ed56234bf2f40d77395673b90ad7e69292165 /src
parentfa918329000c3661a4c6840f952c3247522eb826 (diff)
downloadgem5-c8fc116c7636893517254f785707eba1726d3265.tar.xz
Add a new file which describes an ISA's interrupt handling mechanism. It records when interrupts are requested, and returns an interrupt to execute if the
--HG-- extra : convert_revision : c535000a6a170caefd441687b60f940513d29739
Diffstat (limited to 'src')
-rw-r--r--src/arch/SConscript1
-rw-r--r--src/arch/alpha/interrupts.hh171
-rw-r--r--src/cpu/base.cc43
-rw-r--r--src/cpu/base.hh18
-rw-r--r--src/cpu/o3/alpha/cpu_impl.hh48
-rw-r--r--src/cpu/simple/base.cc37
6 files changed, 194 insertions, 124 deletions
diff --git a/src/arch/SConscript b/src/arch/SConscript
index dda1dea53..092fad225 100644
--- a/src/arch/SConscript
+++ b/src/arch/SConscript
@@ -49,6 +49,7 @@ sources = []
isa_switch_hdrs = Split('''
arguments.hh
faults.hh
+ interrupts.hh
isa_traits.hh
locked_mem.hh
process.hh
diff --git a/src/arch/alpha/interrupts.hh b/src/arch/alpha/interrupts.hh
new file mode 100644
index 000000000..2f031f434
--- /dev/null
+++ b/src/arch/alpha/interrupts.hh
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 2006 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Steve Reinhardt
+ * Kevin Lim
+ */
+
+#ifndef __ARCH_ALPHA_INTERRUPT_HH__
+#define __ARCH_ALPHA_INTERRUPT_HH__
+
+#include "arch/alpha/faults.hh"
+#include "arch/alpha/isa_traits.hh"
+#include "cpu/thread_context.hh"
+
+namespace AlphaISA
+{
+ class Interrupts
+ {
+ protected:
+ uint64_t interrupts[NumInterruptLevels];
+ uint64_t intstatus;
+
+ public:
+ Interrupts()
+ {
+ memset(interrupts, 0, sizeof(interrupts));
+ intstatus = 0;
+ }
+
+ void post(int int_num, int index)
+ {
+ DPRINTF(Interrupt, "Interrupt %d:%d posted\n", int_num, index);
+
+ if (int_num < 0 || int_num >= NumInterruptLevels)
+ panic("int_num out of bounds\n");
+
+ if (index < 0 || index >= sizeof(uint64_t) * 8)
+ panic("int_num out of bounds\n");
+
+ interrupts[int_num] |= 1 << index;
+ intstatus |= (ULL(1) << int_num);
+ }
+
+ void clear(int int_num, int index)
+ {
+ DPRINTF(Interrupt, "Interrupt %d:%d cleared\n", int_num, index);
+
+ if (int_num < 0 || int_num >= TheISA::NumInterruptLevels)
+ panic("int_num out of bounds\n");
+
+ if (index < 0 || index >= sizeof(uint64_t) * 8)
+ panic("int_num out of bounds\n");
+
+ interrupts[int_num] &= ~(1 << index);
+ if (interrupts[int_num] == 0)
+ intstatus &= ~(ULL(1) << int_num);
+ }
+
+ void clear_all()
+ {
+ DPRINTF(Interrupt, "Interrupts all cleared\n");
+
+ memset(interrupts, 0, sizeof(interrupts));
+ intstatus = 0;
+ }
+
+ bool check_interrupt(int int_num) const {
+ if (int_num > NumInterruptLevels)
+ panic("int_num out of bounds\n");
+
+ return interrupts[int_num] != 0;
+ }
+
+ bool check_interrupts() const { return intstatus != 0; }
+
+ void serialize(std::ostream &os)
+ {
+ SERIALIZE_ARRAY(interrupts, NumInterruptLevels);
+ SERIALIZE_SCALAR(intstatus);
+ }
+
+ void unserialize(Checkpoint *cp, const std::string &section)
+ {
+ UNSERIALIZE_ARRAY(interrupts, NumInterruptLevels);
+ UNSERIALIZE_SCALAR(intstatus);
+ }
+
+ Fault getInterrupt(ThreadContext * tc)
+ {
+ int ipl = 0;
+ int summary = 0;
+
+ if (tc->readMiscReg(IPR_ASTRR))
+ panic("asynchronous traps not implemented\n");
+
+ if (tc->readMiscReg(IPR_SIRR)) {
+ for (int i = INTLEVEL_SOFTWARE_MIN;
+ i < INTLEVEL_SOFTWARE_MAX; i++) {
+ if (tc->readMiscReg(IPR_SIRR) & (ULL(1) << i)) {
+ // See table 4-19 of 21164 hardware reference
+ ipl = (i - INTLEVEL_SOFTWARE_MIN) + 1;
+ summary |= (ULL(1) << i);
+ }
+ }
+ }
+
+ uint64_t interrupts = intstatus;
+ if (interrupts) {
+ for (int i = INTLEVEL_EXTERNAL_MIN;
+ i < INTLEVEL_EXTERNAL_MAX; i++) {
+ if (interrupts & (ULL(1) << i)) {
+ // See table 4-19 of 21164 hardware reference
+ ipl = i;
+ summary |= (ULL(1) << i);
+ }
+ }
+ }
+
+ if (ipl && ipl > tc->readMiscReg(IPR_IPLR)) {
+ tc->setMiscReg(IPR_ISR, summary);
+ tc->setMiscReg(IPR_INTID, ipl);
+
+ /* The following needs to be added back in somehow */
+ // Checker needs to know these two registers were updated.
+/*#if USE_CHECKER
+ if (this->checker) {
+ this->checker->threadBase()->setMiscReg(IPR_ISR, summary);
+ this->checker->threadBase()->setMiscReg(IPR_INTID, ipl);
+ }
+#endif*/
+
+ DPRINTF(Flow, "Interrupt! IPLR=%d ipl=%d summary=%x\n",
+ tc->readMiscReg(IPR_IPLR), ipl, summary);
+
+ return new InterruptFault;
+ } else {
+ return NoFault;
+ }
+ }
+
+ private:
+ uint64_t intr_status() const { return intstatus; }
+ };
+}
+
+#endif
+
diff --git a/src/cpu/base.cc b/src/cpu/base.cc
index ea4b03bf2..66c5d3e11 100644
--- a/src/cpu/base.cc
+++ b/src/cpu/base.cc
@@ -168,11 +168,6 @@ BaseCPU::BaseCPU(Params *p)
p->max_loads_all_threads, *counter);
}
-#if FULL_SYSTEM
- memset(interrupts, 0, sizeof(interrupts));
- intstatus = 0;
-#endif
-
functionTracingEnabled = false;
if (p->functionTrace) {
functionTraceStream = simout.find(csprintf("ftrace.%s", name()));
@@ -314,9 +309,7 @@ BaseCPU::takeOverFrom(BaseCPU *oldCPU)
}
#if FULL_SYSTEM
- for (int i = 0; i < TheISA::NumInterruptLevels; ++i)
- interrupts[i] = oldCPU->interrupts[i];
- intstatus = oldCPU->intstatus;
+ interrupts = oldCPU->interrupts;
checkInterrupts = oldCPU->checkInterrupts;
for (int i = 0; i < threadContexts.size(); ++i)
@@ -348,57 +341,33 @@ BaseCPU::ProfileEvent::process()
void
BaseCPU::post_interrupt(int int_num, int index)
{
- DPRINTF(Interrupt, "Interrupt %d:%d posted\n", int_num, index);
-
- if (int_num < 0 || int_num >= TheISA::NumInterruptLevels)
- panic("int_num out of bounds\n");
-
- if (index < 0 || index >= sizeof(uint64_t) * 8)
- panic("int_num out of bounds\n");
-
checkInterrupts = true;
- interrupts[int_num] |= 1 << index;
- intstatus |= (ULL(1) << int_num);
+ interrupts.post(int_num, index);
}
void
BaseCPU::clear_interrupt(int int_num, int index)
{
- DPRINTF(Interrupt, "Interrupt %d:%d cleared\n", int_num, index);
-
- if (int_num < 0 || int_num >= TheISA::NumInterruptLevels)
- panic("int_num out of bounds\n");
-
- if (index < 0 || index >= sizeof(uint64_t) * 8)
- panic("int_num out of bounds\n");
-
- interrupts[int_num] &= ~(1 << index);
- if (interrupts[int_num] == 0)
- intstatus &= ~(ULL(1) << int_num);
+ interrupts.clear(int_num, index);
}
void
BaseCPU::clear_interrupts()
{
- DPRINTF(Interrupt, "Interrupts all cleared\n");
-
- memset(interrupts, 0, sizeof(interrupts));
- intstatus = 0;
+ interrupts.clear_all();
}
void
BaseCPU::serialize(std::ostream &os)
{
- SERIALIZE_ARRAY(interrupts, TheISA::NumInterruptLevels);
- SERIALIZE_SCALAR(intstatus);
+ interrupts.serialize(os);
}
void
BaseCPU::unserialize(Checkpoint *cp, const std::string &section)
{
- UNSERIALIZE_ARRAY(interrupts, TheISA::NumInterruptLevels);
- UNSERIALIZE_SCALAR(intstatus);
+ interrupts.unserialize(cp, section);
}
#endif // FULL_SYSTEM
diff --git a/src/cpu/base.hh b/src/cpu/base.hh
index 75e0d86af..207473d80 100644
--- a/src/cpu/base.hh
+++ b/src/cpu/base.hh
@@ -40,6 +40,10 @@
#include "mem/mem_object.hh"
#include "arch/isa_traits.hh"
+#if FULL_SYSTEM
+#include "arch/interrupts.hh"
+#endif
+
class BranchPred;
class CheckerCPU;
class ThreadContext;
@@ -75,8 +79,9 @@ class BaseCPU : public MemObject
#if FULL_SYSTEM
protected:
- uint64_t interrupts[TheISA::NumInterruptLevels];
- uint64_t intstatus;
+// uint64_t interrupts[TheISA::NumInterruptLevels];
+// uint64_t intstatus;
+ TheISA::Interrupts interrupts;
public:
virtual void post_interrupt(int int_num, int index);
@@ -85,14 +90,11 @@ class BaseCPU : public MemObject
bool checkInterrupts;
bool check_interrupt(int int_num) const {
- if (int_num > TheISA::NumInterruptLevels)
- panic("int_num out of bounds\n");
-
- return interrupts[int_num] != 0;
+ return interrupts.check_interrupt(int_num);
}
- bool check_interrupts() const { return intstatus != 0; }
- uint64_t intr_status() const { return intstatus; }
+ bool check_interrupts() const { return interrupts.check_interrupts(); }
+ //uint64_t intr_status() const { return interrupts.intr_status(); }
class ProfileEvent : public Event
{
diff --git a/src/cpu/o3/alpha/cpu_impl.hh b/src/cpu/o3/alpha/cpu_impl.hh
index f5c2170ce..170a53c23 100644
--- a/src/cpu/o3/alpha/cpu_impl.hh
+++ b/src/cpu/o3/alpha/cpu_impl.hh
@@ -270,7 +270,6 @@ template <class Impl>
void
AlphaO3CPU<Impl>::processInterrupts()
{
- using namespace TheISA;
// Check for interrupts here. For now can copy the code that
// exists within isa_fullsys_traits.hh. Also assume that thread 0
// is the one that handles the interrupts.
@@ -279,52 +278,11 @@ AlphaO3CPU<Impl>::processInterrupts()
// Check if there are any outstanding interrupts
//Handle the interrupts
- int ipl = 0;
- int summary = 0;
-
this->checkInterrupts = false;
+ Fault interrupt = this->interrupts.getInterrupt(this->tcBase(0));
- if (this->readMiscReg(IPR_ASTRR, 0))
- panic("asynchronous traps not implemented\n");
-
- if (this->readMiscReg(IPR_SIRR, 0)) {
- for (int i = INTLEVEL_SOFTWARE_MIN;
- i < INTLEVEL_SOFTWARE_MAX; i++) {
- if (this->readMiscReg(IPR_SIRR, 0) & (ULL(1) << i)) {
- // See table 4-19 of the 21164 hardware reference
- ipl = (i - INTLEVEL_SOFTWARE_MIN) + 1;
- summary |= (ULL(1) << i);
- }
- }
- }
-
- uint64_t interrupts = this->intr_status();
-
- if (interrupts) {
- for (int i = INTLEVEL_EXTERNAL_MIN;
- i < INTLEVEL_EXTERNAL_MAX; i++) {
- if (interrupts & (ULL(1) << i)) {
- // See table 4-19 of the 21164 hardware reference
- ipl = i;
- summary |= (ULL(1) << i);
- }
- }
- }
-
- if (ipl && ipl > this->readMiscReg(IPR_IPLR, 0)) {
- this->setMiscReg(IPR_ISR, summary, 0);
- this->setMiscReg(IPR_INTID, ipl, 0);
- // Checker needs to know these two registers were updated.
-#if USE_CHECKER
- if (this->checker) {
- this->checker->threadBase()->setMiscReg(IPR_ISR, summary);
- this->checker->threadBase()->setMiscReg(IPR_INTID, ipl);
- }
-#endif
- this->trap(Fault(new InterruptFault), 0);
- DPRINTF(Flow, "Interrupt! IPLR=%d ipl=%d summary=%x\n",
- this->readMiscReg(IPR_IPLR, 0), ipl, summary);
- }
+ if (interrupt != NoFault)
+ this->trap(interrupt, 0);
}
#endif // FULL_SYSTEM
diff --git a/src/cpu/simple/base.cc b/src/cpu/simple/base.cc
index 6a2c0bbe9..0c7b5eafe 100644
--- a/src/cpu/simple/base.cc
+++ b/src/cpu/simple/base.cc
@@ -312,42 +312,11 @@ BaseSimpleCPU::checkForInterrupts()
{
#if FULL_SYSTEM
if (checkInterrupts && check_interrupts() && !thread->inPalMode()) {
- int ipl = 0;
- int summary = 0;
checkInterrupts = false;
+ Fault interrupt = interrupts.getInterrupt(tc);
- if (thread->readMiscReg(IPR_SIRR)) {
- for (int i = INTLEVEL_SOFTWARE_MIN;
- i < INTLEVEL_SOFTWARE_MAX; i++) {
- if (thread->readMiscReg(IPR_SIRR) & (ULL(1) << i)) {
- // See table 4-19 of 21164 hardware reference
- ipl = (i - INTLEVEL_SOFTWARE_MIN) + 1;
- summary |= (ULL(1) << i);
- }
- }
- }
-
- uint64_t interrupts = thread->cpu->intr_status();
- for (int i = INTLEVEL_EXTERNAL_MIN;
- i < INTLEVEL_EXTERNAL_MAX; i++) {
- if (interrupts & (ULL(1) << i)) {
- // See table 4-19 of 21164 hardware reference
- ipl = i;
- summary |= (ULL(1) << i);
- }
- }
-
- if (thread->readMiscReg(IPR_ASTRR))
- panic("asynchronous traps not implemented\n");
-
- if (ipl && ipl > thread->readMiscReg(IPR_IPLR)) {
- thread->setMiscReg(IPR_ISR, summary);
- thread->setMiscReg(IPR_INTID, ipl);
-
- Fault(new InterruptFault)->invoke(tc);
-
- DPRINTF(Flow, "Interrupt! IPLR=%d ipl=%d summary=%x\n",
- thread->readMiscReg(IPR_IPLR), ipl, summary);
+ if (interrupt != NoFault) {
+ interrupt->invoke(tc);
}
}
#endif