Add a new file which describes an ISA's interrupt handling mechanism. It records...
authorGabe Black <gblack@eecs.umich.edu>
Fri, 3 Nov 2006 07:25:39 +0000 (02:25 -0500)
committerGabe Black <gblack@eecs.umich.edu>
Fri, 3 Nov 2006 07:25:39 +0000 (02:25 -0500)
--HG--
extra : convert_revision : c535000a6a170caefd441687b60f940513d29739

src/arch/SConscript
src/arch/alpha/interrupts.hh [new file with mode: 0644]
src/cpu/base.cc
src/cpu/base.hh
src/cpu/o3/alpha/cpu_impl.hh
src/cpu/simple/base.cc

index dda1dea532568779df1789ca7c15a70de6b025f8..092fad225543b08a848bbce3d44f9dbe38f6f458 100644 (file)
@@ -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 (file)
index 0000000..2f031f4
--- /dev/null
@@ -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
+
index ea4b03bf286a44f945c3279451e6c492345b132e..66c5d3e11d31991a5f365fcd136b88422f74d399 100644 (file)
@@ -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
index 75e0d86af4e910e221eae6a784475ad7016b80e6..207473d8044ab57185ae3b9de092913614dde57f 100644 (file)
 #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
     {
index f5c2170ce491e769e16f6e5ae68f05f955b983d8..170a53c23b62305e84957e6e684316a69137f981 100644 (file)
@@ -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
index 6a2c0bbe93f47d268c45428ae78e969c0136cfb3..0c7b5eafef249d682311da8271b5df881c9673aa 100644 (file)
@@ -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