diff options
Diffstat (limited to 'src/arch/sparc/interrupts.hh')
-rw-r--r-- | src/arch/sparc/interrupts.hh | 56 |
1 files changed, 55 insertions, 1 deletions
diff --git a/src/arch/sparc/interrupts.hh b/src/arch/sparc/interrupts.hh index 8929759f3..e6c926676 100644 --- a/src/arch/sparc/interrupts.hh +++ b/src/arch/sparc/interrupts.hh @@ -121,12 +121,66 @@ class Interrupts : public SimObject 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); |