changeset b11410957c9e in /z/repo/gem5
details: http://repo.gem5.org/gem5?cmd=changeset;node=b11410957c9e
description:
        isa: Modify get/check interrupt routines

        Make it so that getInterrupt *always* returns an interrupt if
        checkInterrupts() returns true.  This fixes/simplifies handling
        of interrupts on the SMT FS CPUs (currently minor).

diffstat:

 src/arch/alpha/interrupts.hh |  68 +++++++++++++++++++++++++++++--------------
 src/arch/arm/interrupts.hh   |  11 +++---
 src/arch/mips/interrupts.cc  |  31 +++++++++++++------
 src/arch/mips/interrupts.hh  |   8 +----
 src/arch/power/interrupts.hh |   1 +
 src/arch/sparc/interrupts.hh |  56 +++++++++++++++++++++++++++++++++++-
 6 files changed, 130 insertions(+), 45 deletions(-)

diffs (287 lines):

diff -r 9b9116df5e88 -r b11410957c9e src/arch/alpha/interrupts.hh
--- a/src/arch/alpha/interrupts.hh      Thu Jul 21 17:19:15 2016 +0100
+++ b/src/arch/alpha/interrupts.hh      Thu Jul 21 17:19:15 2016 +0100
@@ -137,18 +137,18 @@
     bool
     checkInterrupts(ThreadContext *tc) const
     {
-        return (intstatus != 0) && !(tc->pcState().pc() & 0x3);
-    }
+        if (intstatus == 0)
+            return false;
 
-    Fault
-    getInterrupt(ThreadContext *tc)
-    {
-        uint64_t ipl = 0;
-        uint64_t summary = 0;
+        if (tc->pcState().pc() & 0x3)
+            return false;
 
         if (tc->readMiscRegNoEffect(IPR_ASTRR))
             panic("asynchronous traps not implemented\n");
 
+        uint64_t ipl = 0;
+        uint64_t summary = 0;
+
         if (tc->readMiscRegNoEffect(IPR_SIRR)) {
             for (uint64_t i = INTLEVEL_SOFTWARE_MIN;
                  i < INTLEVEL_SOFTWARE_MAX; i++) {
@@ -160,28 +160,52 @@
             }
         }
 
-        if (intstatus) {
-            for (uint64_t i = INTLEVEL_EXTERNAL_MIN;
-                 i < INTLEVEL_EXTERNAL_MAX; i++) {
-                if (intstatus & (ULL(1) << i)) {
+        for (uint64_t i = INTLEVEL_EXTERNAL_MIN; i < INTLEVEL_EXTERNAL_MAX;
+             i++) {
+            if (intstatus & (ULL(1) << i)) {
+                // See table 4-19 of 21164 hardware reference
+                ipl = i;
+                summary |= (ULL(1) << i);
+            }
+        }
+
+        return ipl && ipl > tc->readMiscRegNoEffect(IPR_IPLR);
+    }
+
+    Fault
+    getInterrupt(ThreadContext *tc)
+    {
+        assert(checkInterrupts(tc));
+
+        uint64_t ipl = 0;
+        uint64_t summary = 0;
+        if (tc->readMiscRegNoEffect(IPR_SIRR)) {
+            for (uint64_t i = INTLEVEL_SOFTWARE_MIN;
+                 i < INTLEVEL_SOFTWARE_MAX; i++) {
+                if (tc->readMiscRegNoEffect(IPR_SIRR) & (ULL(1) << i)) {
                     // See table 4-19 of 21164 hardware reference
-                    ipl = i;
+                    ipl = (i - INTLEVEL_SOFTWARE_MIN) + 1;
                     summary |= (ULL(1) << i);
                 }
             }
         }
 
-        if (ipl && ipl > tc->readMiscRegNoEffect(IPR_IPLR)) {
-            newIpl = ipl;
-            newSummary = summary;
-            newInfoSet = true;
-            DPRINTF(Flow, "Interrupt! IPLR=%d ipl=%d summary=%x\n",
-                    tc->readMiscRegNoEffect(IPR_IPLR), ipl, summary);
+        for (uint64_t i = INTLEVEL_EXTERNAL_MIN; i < INTLEVEL_EXTERNAL_MAX;
+             i++) {
+            if (intstatus & (ULL(1) << i)) {
+                // See table 4-19 of 21164 hardware reference
+                ipl = i;
+                summary |= (ULL(1) << i);
+            }
+        }
 
-            return std::make_shared<InterruptFault>();
-        } else {
-            return NoFault;
-        }
+        newIpl = ipl;
+        newSummary = summary;
+        newInfoSet = true;
+        DPRINTF(Flow, "Interrupt! IPLR=%d ipl=%d summary=%x\n",
+                tc->readMiscRegNoEffect(IPR_IPLR), ipl, summary);
+
+        return std::make_shared<InterruptFault>();
     }
 
     void
diff -r 9b9116df5e88 -r b11410957c9e src/arch/arm/interrupts.hh
--- a/src/arch/arm/interrupts.hh        Thu Jul 21 17:19:15 2016 +0100
+++ b/src/arch/arm/interrupts.hh        Thu Jul 21 17:19:15 2016 +0100
@@ -149,6 +149,10 @@
         bool allowVFiq   = !cpsr.f && hcr.fmo && !isSecure && !isHypMode;
         bool allowVAbort = !cpsr.a && hcr.amo && !isSecure && !isHypMode;
 
+        if ( !(intStatus || (hcr.vi && allowVIrq) || (hcr.vf && allowVFiq) ||
+               (hcr.va && allowVAbort)) )
+            return false;
+
         bool take_irq = takeInt(tc, INT_IRQ);
         bool take_fiq = takeInt(tc, INT_FIQ);
         bool take_ea =  takeInt(tc, INT_ABT);
@@ -221,6 +225,8 @@
     Fault
     getInterrupt(ThreadContext *tc)
     {
+        assert(checkInterrupts(tc));
+
         HCR  hcr  = tc->readMiscReg(MISCREG_HCR);
         CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
         SCR  scr  = tc->readMiscReg(MISCREG_SCR);
@@ -234,15 +240,10 @@
         bool allowVFiq   = !cpsr.f && hcr.fmo && !isSecure && !isHypMode;
         bool allowVAbort = !cpsr.a && hcr.amo && !isSecure && !isHypMode;
 
-        if ( !(intStatus || (hcr.vi && allowVIrq) || (hcr.vf && allowVFiq) ||
-               (hcr.va && allowVAbort)) )
-            return NoFault;
-
         bool take_irq = takeInt(tc, INT_IRQ);
         bool take_fiq = takeInt(tc, INT_FIQ);
         bool take_ea =  takeInt(tc, INT_ABT);
 
-
         if (interrupts[INT_IRQ] && take_irq)
             return std::make_shared<Interrupt>();
         if ((interrupts[INT_VIRT_IRQ] || hcr.vi) && allowVIrq)
diff -r 9b9116df5e88 -r b11410957c9e src/arch/mips/interrupts.cc
--- a/src/arch/mips/interrupts.cc       Thu Jul 21 17:19:15 2016 +0100
+++ b/src/arch/mips/interrupts.cc       Thu Jul 21 17:19:15 2016 +0100
@@ -105,11 +105,11 @@
 }
 
 
-
-Fault
-Interrupts::getInterrupt(ThreadContext * tc)
+bool
+Interrupts::checkInterrupts(ThreadContext *tc) const
 {
-    DPRINTF(Interrupt, "Interrupts getInterrupt\n");
+    if (!interruptsPending(tc))
+        return false;
 
     //Check if there are any outstanding interrupts
     StatusReg status = tc->readMiscRegNoEffect(MISCREG_STATUS);
@@ -120,14 +120,25 @@
         // So if any interrupt that isn't masked is detected, jump to interrupt
         // handler
         CauseReg cause = tc->readMiscRegNoEffect(MISCREG_CAUSE);
-        if (status.im && cause.ip) {
-            DPRINTF(Interrupt, "Interrupt! IM[7:0]=%d IP[7:0]=%d \n",
-                    (unsigned)status.im, (unsigned)cause.ip);
-            return std::make_shared<InterruptFault>();
-        }
+        if (status.im && cause.ip)
+            return true;
+
     }
 
-    return NoFault;
+    return false;
+}
+
+Fault
+Interrupts::getInterrupt(ThreadContext * tc)
+{
+    assert(checkInterrupts(tc));
+
+    StatusReg M5_VAR_USED status = tc->readMiscRegNoEffect(MISCREG_STATUS);
+    CauseReg M5_VAR_USED cause = tc->readMiscRegNoEffect(MISCREG_CAUSE);
+    DPRINTF(Interrupt, "Interrupt! IM[7:0]=%d IP[7:0]=%d \n",
+            (unsigned)status.im, (unsigned)cause.ip);
+
+    return std::make_shared<InterruptFault>();
 }
 
 bool
diff -r 9b9116df5e88 -r b11410957c9e src/arch/mips/interrupts.hh
--- a/src/arch/mips/interrupts.hh       Thu Jul 21 17:19:15 2016 +0100
+++ b/src/arch/mips/interrupts.hh       Thu Jul 21 17:19:15 2016 +0100
@@ -107,13 +107,7 @@
     void updateIntrInfo(ThreadContext *tc) const;
     bool interruptsPending(ThreadContext *tc) const;
     bool onCpuTimerInterrupt(ThreadContext *tc) const;
-
-    bool
-    checkInterrupts(ThreadContext *tc) const
-    {
-        return interruptsPending(tc);
-    }
-
+    bool checkInterrupts(ThreadContext *tc) const;
 
     void
     serialize(CheckpointOut &cp) const override
diff -r 9b9116df5e88 -r b11410957c9e src/arch/power/interrupts.hh
--- a/src/arch/power/interrupts.hh      Thu Jul 21 17:19:15 2016 +0100
+++ b/src/arch/power/interrupts.hh      Thu Jul 21 17:19:15 2016 +0100
@@ -89,6 +89,7 @@
     Fault
     getInterrupt(ThreadContext *tc)
     {
+        assert(checkInterrupts(tc));
         panic("Interrupts::getInterrupt not implemented.\n");
     }
 
diff -r 9b9116df5e88 -r b11410957c9e src/arch/sparc/interrupts.hh
--- a/src/arch/sparc/interrupts.hh      Thu Jul 21 17:19:15 2016 +0100
+++ b/src/arch/sparc/interrupts.hh      Thu Jul 21 17:19:15 2016 +0100
@@ -121,12 +121,66 @@
     bool
     checkInterrupts(ThreadContext *tc) const
     {
-        return intStatus;
+        if (!intStatus)
+            return false;
+
+        HPSTATE hpstate = tc->readMiscRegNoEffect(MISCREG_HPSTATE);
+        PSTATE pstate = tc->readMiscRegNoEffect(MISCREG_PSTATE);
+
+        // THESE ARE IN ORDER OF PRIORITY
+        // since there are early returns, and the highest
+        // priority interrupts should get serviced,
+        // it is v. important that new interrupts are inserted
+        // in the right order of processing
+        if (hpstate.hpriv) {
+            if (pstate.ie) {
+                if (interrupts[IT_HINTP]) {
+                    // This will be cleaned by a HINTP write
+                    return true;
+                }
+                if (interrupts[IT_INT_VEC]) {
+                    // this will be cleared by an ASI read (or write)
+                    return true;
+                }
+            }
+        } else {
+            if (interrupts[IT_TRAP_LEVEL_ZERO]) {
+                    // this is cleared by deasserting HPSTATE::tlz
+                return true;
+            }
+            // HStick matches always happen in priv mode (ie doesn't matter)
+            if (interrupts[IT_HINTP]) {
+                return true;
+            }
+            if (interrupts[IT_INT_VEC]) {
+                // this will be cleared by an ASI read (or write)
+                return true;
+            }
+            if (pstate.ie) {
+                if (interrupts[IT_CPU_MONDO]) {
+                    return true;
+                }
+                if (interrupts[IT_DEV_MONDO]) {
+                    return true;
+                }
+                if (interrupts[IT_SOFT_INT]) {
+                    return true;
+                }
+
+                if (interrupts[IT_RES_ERROR]) {
+                    return true;
+                }
+            } // !hpriv && pstate.ie
+        }  // !hpriv
+
+        return false;
     }
 
     Fault
     getInterrupt(ThreadContext *tc)
     {
+        assert(checkInterrupts(tc));
+
         HPSTATE hpstate = tc->readMiscRegNoEffect(MISCREG_HPSTATE);
         PSTATE pstate = tc->readMiscRegNoEffect(MISCREG_PSTATE);
 
_______________________________________________
gem5-dev mailing list
gem5-dev@gem5.org
http://m5sim.org/mailman/listinfo/gem5-dev

Reply via email to