From 032ea9b2db870ad9b2a039f8c4020e38f5dd7f62 Mon Sep 17 00:00:00 2001 From: Lisa Hsu Date: Mon, 8 Jan 2007 18:18:28 -0500 Subject: [PATCH] the way i understand it, interrupts in m5 is a little bloated. the usage of CPU->checkInterrupts bool is inconsistent, and i think should eventually be phased out. For now, I've just assumed that CPU->checkInterrupts() is the way to fast path a CPU if you have no interrupts by having a simple bitfield in each ISA to determine whether interrupts are pending. getInterrupts has been mostly filled in. src/arch/sparc/interrupts.hh: fill in how we do interrupts on sparc a little bit. 1) create a bitfield for interrupts, and check that in checkInterrupts() to fast path CPU. 2) fill in getInterrupts() a little bit. also, update the bitfield access to be HPSTATE::hpriv, etc. src/arch/sparc/ua2005.cc: 1) update formatting 2) change the way interrupts are done to use the new way to tickle the CPU. src/cpu/base.cc: src/cpu/base.hh: overload the post_interrupt function for SPARC interrupts - which are only denoted by a single int value. --HG-- extra : convert_revision : 9074a003eff37a40dcce78f56d20f6cbcc453eb5 --- src/arch/sparc/interrupts.hh | 125 +++++++++++++++++++++-- src/arch/sparc/ua2005.cc | 188 ++++++++++++++++++----------------- src/cpu/base.cc | 6 ++ src/cpu/base.hh | 1 + 4 files changed, 219 insertions(+), 101 deletions(-) diff --git a/src/arch/sparc/interrupts.hh b/src/arch/sparc/interrupts.hh index 452164e46..76bd4c6e2 100644 --- a/src/arch/sparc/interrupts.hh +++ b/src/arch/sparc/interrupts.hh @@ -34,19 +34,45 @@ #include "arch/sparc/faults.hh" #include "cpu/thread_context.hh" - namespace SparcISA { + +enum interrupts_t { + trap_level_zero, + hstick_match, + interrupt_vector, + cpu_mondo, + dev_mondo, + resumable_error, + soft_interrupt, + num_interrupt_types +}; + class Interrupts { - protected: + private: + + bool interrupts[num_interrupt_types]; + int numPosted; public: Interrupts() { - + for (int i = 0; i < num_interrupt_types; ++i) { + interrupts[i] = false; + } + numPosted = 0; } + + void post(int int_type) + { + if (int_type < 0 || int_type >= num_interrupt_types) + panic("posting unknown interrupt!\n"); + interrupts[int_type] = true; + ++numPosted; + } + void post(int int_num, int index) { @@ -64,9 +90,7 @@ namespace SparcISA bool check_interrupts(ThreadContext * tc) const { - // so far only handle softint interrupts - int int_level = InterruptLevel(tc->readMiscReg(MISCREG_SOFTINT)); - if (int_level) + if (numPosted) return true; else return false; @@ -74,14 +98,99 @@ namespace SparcISA Fault getInterrupt(ThreadContext * tc) { + int hpstate = tc->readMiscReg(MISCREG_HPSTATE); + int pstate = tc->readMiscReg(MISCREG_PSTATE); + bool ie = pstate & PSTATE::ie; + + // 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 & HPSTATE::hpriv) { + if (ie) { + if (interrupts[hstick_match]) { + interrupts[hstick_match] = false; + --numPosted; + return new HstickMatch; + } + if (interrupts[interrupt_vector]) { + interrupts[interrupt_vector] = false; + --numPosted; + //HAVEN'T IMPLed THIS YET + return NoFault; + } + } + } else { + + if (interrupts[trap_level_zero]) { + //HAVEN'T IMPLed YET + if ((pstate & HPSTATE::tlz) && (tc->readMiscReg(MISCREG_TL) == 0)) { + interrupts[trap_level_zero] = false; + --numPosted; + return NoFault; + } + } + if (interrupts[hstick_match]) { + interrupts[hstick_match] = false; + --numPosted; + return new HstickMatch; + } + if (ie) { + if (interrupts[cpu_mondo]) { + interrupts[cpu_mondo] = false; + --numPosted; + return new CpuMondo; + } + if (interrupts[dev_mondo]) { + interrupts[dev_mondo] = false; + --numPosted; + return new DevMondo; + } + if (interrupts[soft_interrupt]) { + int il = InterruptLevel(tc->readMiscReg(MISCREG_SOFTINT)); + // it seems that interrupt vectors are right in + // the middle of interrupt levels with regard to + // priority, so have to check + if ((il < 6) && + interrupts[interrupt_vector]) { + // may require more details here since there + // may be lots of interrupts embedded in an + // platform interrupt vector + interrupts[interrupt_vector] = false; + --numPosted; + //HAVEN'T IMPLed YET + return NoFault; + } else { + if (il > tc->readMiscReg(MISCREG_PIL)) { + uint64_t si = tc->readMiscReg(MISCREG_SOFTINT); + uint64_t more = si & ~(1 << (il + 1)); + if (!InterruptLevel(more)) { + interrupts[soft_interrupt] = false; + --numPosted; + } + return new InterruptLevelN(il); + } + } + } + if (interrupts[resumable_error]) { + interrupts[resumable_error] = false; + --numPosted; + return new ResumableError; + } + } + } + return NoFault; + + // conditioning the softint interrups - if (tc->readMiscReg(MISCREG_HPSTATE) & hpriv) { + if (tc->readMiscReg(MISCREG_HPSTATE) & HPSTATE::hpriv) { // if running in privileged mode, then pend the interrupt return NoFault; } else { int int_level = InterruptLevel(tc->readMiscReg(MISCREG_SOFTINT)); if ((int_level <= tc->readMiscReg(MISCREG_PIL)) || - !(tc->readMiscReg(MISCREG_PSTATE) & ie)) { + !(tc->readMiscReg(MISCREG_PSTATE) & PSTATE::ie)) { // if PIL or no interrupt enabled, then pend the interrupt return NoFault; } else { diff --git a/src/arch/sparc/ua2005.cc b/src/arch/sparc/ua2005.cc index 1f7f65045..c153c2d52 100644 --- a/src/arch/sparc/ua2005.cc +++ b/src/arch/sparc/ua2005.cc @@ -38,105 +38,105 @@ using namespace SparcISA; void MiscRegFile::setFSRegWithEffect(int miscReg, const MiscReg &val, - ThreadContext *tc) + ThreadContext *tc) { int64_t time; switch (miscReg) { /* Full system only ASRs */ - case MISCREG_SOFTINT: - // Check if we are going to interrupt because of something - setReg(miscReg, val); - tc->getCpuPtr()->checkInterrupts = true; - warn("Writing to softint not really supported, writing: %#x\n", val); - break; + case MISCREG_SOFTINT: + // Check if we are going to interrupt because of something + setReg(miscReg, val); + tc->getCpuPtr()->post_interrupt(soft_interrupt); + warn("Writing to softint not really supported, writing: %#x\n", val); + break; - case MISCREG_SOFTINT_CLR: - return setRegWithEffect(MISCREG_SOFTINT, ~val & softint, tc); - case MISCREG_SOFTINT_SET: - return setRegWithEffect(MISCREG_SOFTINT, val | softint, tc); + case MISCREG_SOFTINT_CLR: + return setRegWithEffect(MISCREG_SOFTINT, ~val & softint, tc); + case MISCREG_SOFTINT_SET: + return setRegWithEffect(MISCREG_SOFTINT, val | softint, tc); - case MISCREG_TICK_CMPR: - if (tickCompare == NULL) - tickCompare = new TickCompareEvent(this, tc); - setReg(miscReg, val); - if ((tick_cmpr & mask(63)) && tickCompare->scheduled()) - tickCompare->deschedule(); - time = (tick_cmpr & mask(63)) - (tick & mask(63)); - if (!(tick_cmpr & ~mask(63)) && time > 0) - tickCompare->schedule(time * tc->getCpuPtr()->cycles(1)); - panic("writing to TICK compare register %#X\n", val); - break; + case MISCREG_TICK_CMPR: + if (tickCompare == NULL) + tickCompare = new TickCompareEvent(this, tc); + setReg(miscReg, val); + if ((tick_cmpr & mask(63)) && tickCompare->scheduled()) + tickCompare->deschedule(); + time = (tick_cmpr & mask(63)) - (tick & mask(63)); + if (!(tick_cmpr & ~mask(63)) && time > 0) + tickCompare->schedule(time * tc->getCpuPtr()->cycles(1)); + panic("writing to TICK compare register %#X\n", val); + break; - case MISCREG_STICK_CMPR: - if (sTickCompare == NULL) - sTickCompare = new STickCompareEvent(this, tc); - setReg(miscReg, val); - if ((stick_cmpr & ~mask(63)) && sTickCompare->scheduled()) - sTickCompare->deschedule(); - time = ((int64_t)(stick_cmpr & mask(63)) - (int64_t)stick) - - tc->getCpuPtr()->instCount(); - if (!(stick_cmpr & ~mask(63)) && time > 0) - sTickCompare->schedule(time * tc->getCpuPtr()->cycles(1) + curTick); - DPRINTF(Timer, "writing to sTICK compare register value %#X\n", val); - break; + case MISCREG_STICK_CMPR: + if (sTickCompare == NULL) + sTickCompare = new STickCompareEvent(this, tc); + setReg(miscReg, val); + if ((stick_cmpr & ~mask(63)) && sTickCompare->scheduled()) + sTickCompare->deschedule(); + time = ((int64_t)(stick_cmpr & mask(63)) - (int64_t)stick) - + tc->getCpuPtr()->instCount(); + if (!(stick_cmpr & ~mask(63)) && time > 0) + sTickCompare->schedule(time * tc->getCpuPtr()->cycles(1) + curTick); + DPRINTF(Timer, "writing to sTICK compare register value %#X\n", val); + break; - case MISCREG_PSTATE: - if (val & ie && !(pstate & ie)) { - tc->getCpuPtr()->checkInterrupts = true; - } - setReg(miscReg, val); + case MISCREG_PSTATE: + if (val & ie && !(pstate & ie)) { + tc->getCpuPtr()->checkInterrupts = true; + } + setReg(miscReg, val); - case MISCREG_PIL: - if (val < pil) { - tc->getCpuPtr()->checkInterrupts = true; - } - setReg(miscReg, val); - break; + case MISCREG_PIL: + if (val < pil) { + tc->getCpuPtr()->checkInterrupts = true; + } + setReg(miscReg, val); + break; - case MISCREG_HVER: - panic("Shouldn't be writing HVER\n"); + case MISCREG_HVER: + panic("Shouldn't be writing HVER\n"); - case MISCREG_HTBA: - // clear lower 7 bits on writes. - setReg(miscReg, val & ULL(~0x7FFF)); - break; + case MISCREG_HTBA: + // clear lower 7 bits on writes. + setReg(miscReg, val & ULL(~0x7FFF)); + break; - case MISCREG_QUEUE_CPU_MONDO_HEAD: - case MISCREG_QUEUE_CPU_MONDO_TAIL: - case MISCREG_QUEUE_DEV_MONDO_HEAD: - case MISCREG_QUEUE_DEV_MONDO_TAIL: - case MISCREG_QUEUE_RES_ERROR_HEAD: - case MISCREG_QUEUE_RES_ERROR_TAIL: - case MISCREG_QUEUE_NRES_ERROR_HEAD: - case MISCREG_QUEUE_NRES_ERROR_TAIL: - setReg(miscReg, val); - tc->getCpuPtr()->checkInterrupts = true; - break; + case MISCREG_QUEUE_CPU_MONDO_HEAD: + case MISCREG_QUEUE_CPU_MONDO_TAIL: + case MISCREG_QUEUE_DEV_MONDO_HEAD: + case MISCREG_QUEUE_DEV_MONDO_TAIL: + case MISCREG_QUEUE_RES_ERROR_HEAD: + case MISCREG_QUEUE_RES_ERROR_TAIL: + case MISCREG_QUEUE_NRES_ERROR_HEAD: + case MISCREG_QUEUE_NRES_ERROR_TAIL: + setReg(miscReg, val); + tc->getCpuPtr()->checkInterrupts = true; + break; - case MISCREG_HSTICK_CMPR: - if (hSTickCompare == NULL) - hSTickCompare = new HSTickCompareEvent(this, tc); - setReg(miscReg, val); - if ((hstick_cmpr & ~mask(63)) && hSTickCompare->scheduled()) - hSTickCompare->deschedule(); - time = ((int64_t)(hstick_cmpr & mask(63)) - (int64_t)stick) - - tc->getCpuPtr()->instCount(); - if (!(hstick_cmpr & ~mask(63)) && time > 0) - hSTickCompare->schedule(curTick + time * tc->getCpuPtr()->cycles(1)); - DPRINTF(Timer, "writing to hsTICK compare register value %#X\n", val); - break; + case MISCREG_HSTICK_CMPR: + if (hSTickCompare == NULL) + hSTickCompare = new HSTickCompareEvent(this, tc); + setReg(miscReg, val); + if ((hstick_cmpr & ~mask(63)) && hSTickCompare->scheduled()) + hSTickCompare->deschedule(); + time = ((int64_t)(hstick_cmpr & mask(63)) - (int64_t)stick) - + tc->getCpuPtr()->instCount(); + if (!(hstick_cmpr & ~mask(63)) && time > 0) + hSTickCompare->schedule(curTick + time * tc->getCpuPtr()->cycles(1)); + DPRINTF(Timer, "writing to hsTICK compare register value %#X\n", val); + break; - case MISCREG_HPSTATE: - // T1000 spec says impl. dependent val must always be 1 - setReg(miscReg, val | id); - break; - case MISCREG_HTSTATE: - case MISCREG_STRAND_STS_REG: - setReg(miscReg, val); - break; + case MISCREG_HPSTATE: + // T1000 spec says impl. dependent val must always be 1 + setReg(miscReg, val | id); + break; + case MISCREG_HTSTATE: + case MISCREG_STRAND_STS_REG: + setReg(miscReg, val); + break; - default: - panic("Invalid write to FS misc register %s\n", getMiscRegName(miscReg)); + default: + panic("Invalid write to FS misc register %s\n", getMiscRegName(miscReg)); } } @@ -144,7 +144,7 @@ MiscReg MiscRegFile::readFSRegWithEffect(int miscReg, ThreadContext * tc) { switch (miscReg) { - /* Privileged registers. */ + /* Privileged registers. */ case MISCREG_QUEUE_CPU_MONDO_HEAD: case MISCREG_QUEUE_CPU_MONDO_TAIL: case MISCREG_QUEUE_DEV_MONDO_HEAD: @@ -174,12 +174,12 @@ MiscRegFile::readFSRegWithEffect(int miscReg, ThreadContext * tc) } } /* - In Niagra STICK==TICK so this isn't needed - case MISCREG_STICK: - SparcSystem *sys; - sys = dynamic_cast(tc->getSystemPtr()); - assert(sys != NULL); - return curTick/Clock::Int::ns - sys->sysTick | (stick & ~(mask(63))); + In Niagra STICK==TICK so this isn't needed + case MISCREG_STICK: + SparcSystem *sys; + sys = dynamic_cast(tc->getSystemPtr()); + assert(sys != NULL); + return curTick/Clock::Int::ns - sys->sysTick | (stick & ~(mask(63))); */ @@ -198,12 +198,13 @@ MiscRegFile::processSTickCompare(ThreadContext *tc) // more int ticks; ticks = ((int64_t)(stick_cmpr & mask(63)) - (int64_t)stick) - - tc->getCpuPtr()->instCount(); + tc->getCpuPtr()->instCount(); assert(ticks >= 0 && "stick compare missed interrupt cycle"); if (ticks == 0) { DPRINTF(Timer, "STick compare cycle reached at %#x\n", (stick_cmpr & mask(63))); + tc->getCpuPtr()->post_interrupt(soft_interrupt); tc->getCpuPtr()->checkInterrupts = true; softint |= ULL(1) << 16; } else @@ -218,12 +219,13 @@ MiscRegFile::processHSTickCompare(ThreadContext *tc) // more int ticks; ticks = ((int64_t)(hstick_cmpr & mask(63)) - (int64_t)stick) - - tc->getCpuPtr()->instCount(); + tc->getCpuPtr()->instCount(); assert(ticks >= 0 && "hstick compare missed interrupt cycle"); if (ticks == 0) { DPRINTF(Timer, "HSTick compare cycle reached at %#x\n", (stick_cmpr & mask(63))); + tc->getCpuPtr()->post_interrupt(hstick_match); tc->getCpuPtr()->checkInterrupts = true; // Need to do something to cause interrupt to happen here !!! @todo } else diff --git a/src/cpu/base.cc b/src/cpu/base.cc index 31604ad58..b03bc19a5 100644 --- a/src/cpu/base.cc +++ b/src/cpu/base.cc @@ -362,6 +362,12 @@ BaseCPU::ProfileEvent::process() schedule(curTick + interval); } +void +BaseCPU::post_interrupt(int int_type) +{ + interrupts.post(int_type); +} + void BaseCPU::post_interrupt(int int_num, int index) { diff --git a/src/cpu/base.hh b/src/cpu/base.hh index 8c6b079da..89c7d9dda 100644 --- a/src/cpu/base.hh +++ b/src/cpu/base.hh @@ -102,6 +102,7 @@ class BaseCPU : public MemObject TheISA::Interrupts interrupts; public: + virtual void post_interrupt(int int_type); virtual void post_interrupt(int int_num, int index); virtual void clear_interrupt(int int_num, int index); virtual void clear_interrupts();