summaryrefslogtreecommitdiff
path: root/src/arch/sparc/interrupts.hh
diff options
context:
space:
mode:
Diffstat (limited to 'src/arch/sparc/interrupts.hh')
-rw-r--r--src/arch/sparc/interrupts.hh56
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);