summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/arch/alpha/interrupts.hh5
-rw-r--r--src/arch/alpha/pagetable.hh2
-rw-r--r--src/arch/sparc/faults.cc40
-rw-r--r--src/arch/sparc/faults.hh2
-rw-r--r--src/arch/sparc/interrupts.hh134
-rw-r--r--src/arch/sparc/isa_traits.hh9
-rw-r--r--src/arch/sparc/miscregfile.cc4
-rw-r--r--src/arch/sparc/miscregfile.hh30
-rw-r--r--src/arch/sparc/ua2005.cc228
-rw-r--r--src/cpu/base.cc6
-rw-r--r--src/cpu/base.hh1
11 files changed, 286 insertions, 175 deletions
diff --git a/src/arch/alpha/interrupts.hh b/src/arch/alpha/interrupts.hh
index 388ccacde..a522dec6c 100644
--- a/src/arch/alpha/interrupts.hh
+++ b/src/arch/alpha/interrupts.hh
@@ -52,6 +52,11 @@ namespace AlphaISA
newInfoSet = false;
}
+ void post(int int_type)
+ {
+ // sparc only
+ }
+
void post(int int_num, int index)
{
DPRINTF(Interrupt, "Interrupt %d:%d posted\n", int_num, index);
diff --git a/src/arch/alpha/pagetable.hh b/src/arch/alpha/pagetable.hh
index 7ec4a6a75..c7e1c8923 100644
--- a/src/arch/alpha/pagetable.hh
+++ b/src/arch/alpha/pagetable.hh
@@ -80,7 +80,7 @@ namespace AlphaISA {
bool _kre() const { return (entry >> 8) & 0x1; }
bool _nomb() const { return (entry >> 7) & 0x1; }
int _gh() const { return (entry >> 5) & 0x3; }
- bool _asm() const { return (entry >> 4) & 0x1; }
+ bool _asm_() const { return (entry >> 4) & 0x1; }
bool _foe() const { return (entry >> 3) & 0x1; }
bool _fow() const { return (entry >> 2) & 0x1; }
bool _for() const { return (entry >> 1) & 0x1; }
diff --git a/src/arch/sparc/faults.cc b/src/arch/sparc/faults.cc
index af80238df..a74eebafa 100644
--- a/src/arch/sparc/faults.cc
+++ b/src/arch/sparc/faults.cc
@@ -240,7 +240,7 @@ template<> SparcFaultBase::FaultVals
{"dev_mondo", 0x07D, 1611, {P, P, SH}};
template<> SparcFaultBase::FaultVals
- SparcFault<ResumeableError>::vals =
+ SparcFault<ResumableError>::vals =
{"resume_error", 0x07E, 3330, {P, P, SH}};
template<> SparcFaultBase::FaultVals
@@ -436,7 +436,7 @@ void doNormalFault(ThreadContext *tc, TrapType tt, bool gotoHpriv)
tc->setMiscReg(MISCREG_TT, tt);
//Update the global register level
- if(!gotoHpriv)
+ if (!gotoHpriv)
tc->setMiscRegWithEffect(MISCREG_GL, min<int>(GL+1, MaxPGL));
else
tc->setMiscRegWithEffect(MISCREG_GL, min<int>(GL+1, MaxGL));
@@ -448,7 +448,7 @@ void doNormalFault(ThreadContext *tc, TrapType tt, bool gotoHpriv)
PSTATE |= (1 << 4);
//PSTATE.am = 0
PSTATE &= ~(1 << 3);
- if(!gotoHpriv)
+ if (!gotoHpriv)
{
//PSTATE.priv = 1
PSTATE |= (1 << 2);
@@ -471,7 +471,7 @@ void doNormalFault(ThreadContext *tc, TrapType tt, bool gotoHpriv)
//XXX Where exactly is this field?
tc->setMiscReg(MISCREG_PSTATE, PSTATE);
- if(gotoHpriv)
+ if (gotoHpriv)
{
//HPSTATE.red = 0
HPSTATE &= ~(1 << 5);
@@ -484,16 +484,16 @@ void doNormalFault(ThreadContext *tc, TrapType tt, bool gotoHpriv)
}
bool changedCWP = true;
- if(tt == 0x24)
+ if (tt == 0x24)
CWP++;
- else if(0x80 <= tt && tt <= 0xbf)
+ else if (0x80 <= tt && tt <= 0xbf)
CWP += (CANSAVE + 2);
- else if(0xc0 <= tt && tt <= 0xff)
+ else if (0xc0 <= tt && tt <= 0xff)
CWP--;
else
changedCWP = false;
- if(changedCWP)
+ if (changedCWP)
{
CWP = (CWP + NWindows) % NWindows;
tc->setMiscRegWithEffect(MISCREG_CWP, CWP);
@@ -534,45 +534,45 @@ void SparcFaultBase::invoke(ThreadContext * tc)
//We can refer to this to see what the trap level -was-, but something
//in the middle could change it in the regfile out from under us.
- MiscReg TL = tc->readMiscReg(MISCREG_TL);
- MiscReg TT = tc->readMiscReg(MISCREG_TT);
- MiscReg PSTATE = tc->readMiscReg(MISCREG_PSTATE);
- MiscReg HPSTATE = tc->readMiscReg(MISCREG_HPSTATE);
+ MiscReg tl = tc->readMiscReg(MISCREG_TL);
+ MiscReg tt = tc->readMiscReg(MISCREG_TT);
+ MiscReg pstate = tc->readMiscReg(MISCREG_PSTATE);
+ MiscReg hpstate = tc->readMiscReg(MISCREG_HPSTATE);
Addr PC, NPC;
PrivilegeLevel current;
- if(HPSTATE & (1 << 2))
+ if (hpstate & HPSTATE::hpriv)
current = Hyperprivileged;
- else if(PSTATE & (1 << 2))
+ else if (pstate & PSTATE::priv)
current = Privileged;
else
current = User;
PrivilegeLevel level = getNextLevel(current);
- if(HPSTATE & (1 << 5) || TL == MaxTL - 1) {
+ if ((hpstate & HPSTATE::red) || (tl == MaxTL - 1)) {
getREDVector(5, PC, NPC);
- doREDFault(tc, TT);
+ doREDFault(tc, tt);
//This changes the hpstate and pstate, so we need to make sure we
//save the old version on the trap stack in doREDFault.
enterREDState(tc);
- } else if(TL == MaxTL) {
+ } else if (tl == MaxTL) {
panic("Should go to error state here.. crap\n");
//Do error_state somehow?
//Probably inject a WDR fault using the interrupt mechanism.
//What should the PC and NPC be set to?
- } else if(TL > MaxPTL && level == Privileged) {
+ } else if (tl > MaxPTL && level == Privileged) {
//guest_watchdog fault
doNormalFault(tc, trapType(), true);
getHyperVector(tc, PC, NPC, 2);
- } else if(level == Hyperprivileged ||
+ } else if (level == Hyperprivileged ||
level == Privileged && trapType() >= 384) {
doNormalFault(tc, trapType(), true);
getHyperVector(tc, PC, NPC, trapType());
} else {
doNormalFault(tc, trapType(), false);
- getPrivVector(tc, PC, NPC, trapType(), TL+1);
+ getPrivVector(tc, PC, NPC, trapType(), tl+1);
}
tc->setPC(PC);
diff --git a/src/arch/sparc/faults.hh b/src/arch/sparc/faults.hh
index 6b3820ddd..3c0d9674f 100644
--- a/src/arch/sparc/faults.hh
+++ b/src/arch/sparc/faults.hh
@@ -210,7 +210,7 @@ class CpuMondo : public SparcFault<CpuMondo> {};
class DevMondo : public SparcFault<DevMondo> {};
-class ResumeableError : public SparcFault<ResumeableError> {};
+class ResumableError : public SparcFault<ResumableError> {};
class SpillNNormal : public EnumeratedFault<SpillNNormal>
{
diff --git a/src/arch/sparc/interrupts.hh b/src/arch/sparc/interrupts.hh
index 452164e46..99ddb4919 100644
--- a/src/arch/sparc/interrupts.hh
+++ b/src/arch/sparc/interrupts.hh
@@ -24,8 +24,6 @@
* 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: Gabe Black
*/
#ifndef __ARCH_SPARC_INTERRUPT_HH__
@@ -34,19 +32,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 +88,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,20 +96,96 @@ namespace SparcISA
Fault getInterrupt(ThreadContext * tc)
{
- // conditioning the softint interrups
- if (tc->readMiscReg(MISCREG_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)) {
- // if PIL or no interrupt enabled, then pend the interrupt
- return NoFault;
+ 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]) {
+ if (tc->readMiscReg(MISCREG_HINTP) & 1) {
+ 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 {
- return new InterruptLevelN(int_level);
+ if (interrupts[hstick_match]) {
+ return NoFault;
+ }
+
+ }
+ } else {
+ if (interrupts[trap_level_zero]) {
+ if ((pstate & HPSTATE::tlz) && (tc->readMiscReg(MISCREG_TL) == 0)) {
+ interrupts[trap_level_zero] = false;
+ --numPosted;
+ return new TrapLevelZero;
+ }
+ }
+ if (interrupts[hstick_match]) {
+ if (tc->readMiscReg(MISCREG_HINTP) & 1) {
+ 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;
}
void updateIntrInfo(ThreadContext * tc)
diff --git a/src/arch/sparc/isa_traits.hh b/src/arch/sparc/isa_traits.hh
index 3f0b9cad5..8aa8ea7f3 100644
--- a/src/arch/sparc/isa_traits.hh
+++ b/src/arch/sparc/isa_traits.hh
@@ -96,15 +96,6 @@ namespace SparcISA
StaticInstPtr decodeInst(ExtMachInst);
#if FULL_SYSTEM
- ////////// Interrupt Stuff ///////////
- enum InterruptLevels
- {
- INTLEVEL_MIN = 1,
- INTLEVEL_MAX = 15,
-
- NumInterruptLevels = INTLEVEL_MAX - INTLEVEL_MIN
- };
-
// I don't know what it's for, so I don't
// know what SPARC's value should be
// For loading... XXX This maybe could be USegEnd?? --ali
diff --git a/src/arch/sparc/miscregfile.cc b/src/arch/sparc/miscregfile.cc
index 50f510289..d9fcb0280 100644
--- a/src/arch/sparc/miscregfile.cc
+++ b/src/arch/sparc/miscregfile.cc
@@ -214,7 +214,7 @@ MiscReg MiscRegFile::readReg(int miscReg)
case MISCREG_HTSTATE:
return htstate[tl-1];
case MISCREG_HINTP:
- panic("HINTP not implemented\n");
+ return hintp;
case MISCREG_HTBA:
return htba;
case MISCREG_HVER:
@@ -468,7 +468,7 @@ void MiscRegFile::setReg(int miscReg, const MiscReg &val)
htstate[tl-1] = val;
break;
case MISCREG_HINTP:
- panic("HINTP not implemented\n");
+ hintp = val;
case MISCREG_HTBA:
htba = val;
break;
diff --git a/src/arch/sparc/miscregfile.hh b/src/arch/sparc/miscregfile.hh
index c879fd357..8a2e8e810 100644
--- a/src/arch/sparc/miscregfile.hh
+++ b/src/arch/sparc/miscregfile.hh
@@ -142,24 +142,26 @@ namespace SparcISA
MISCREG_NUMMISCREGS
};
- enum HPStateFields {
- id = 0x800, // this impl. dependent (id) field must always be '1' for T1000
- ibe = 0x400,
- red = 0x20,
- hpriv = 0x4,
- tlz = 0x1
+ struct HPSTATE {
+ const static uint64_t id = 0x800; // this impl. dependent (id) field m
+ const static uint64_t ibe = 0x400;
+ const static uint64_t red = 0x20;
+ const static uint64_t hpriv = 0x4;
+ const static uint64_t tlz = 0x1;
};
- enum PStateFields {
- cle = 0x200,
- tle = 0x100,
- mm = 0xC0,
- pef = 0x10,
- am = 0x8,
- priv = 0x4,
- ie = 0x2
+
+ struct PSTATE {
+ const static int cle = 0x200;
+ const static int tle = 0x100;
+ const static int mm = 0xC0;
+ const static int pef = 0x10;
+ const static int am = 0x8;
+ const static int priv = 0x4;
+ const static int ie = 0x2;
};
+
const int NumMiscArchRegs = MISCREG_NUMMISCREGS;
const int NumMiscRegs = MISCREG_NUMMISCREGS;
diff --git a/src/arch/sparc/ua2005.cc b/src/arch/sparc/ua2005.cc
index f03c4da57..6220e6dec 100644
--- a/src/arch/sparc/ua2005.cc
+++ b/src/arch/sparc/ua2005.cc
@@ -24,8 +24,6 @@
* 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: Ali Saidi
*/
#include "arch/sparc/miscregfile.hh"
@@ -38,106 +36,109 @@ 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;
- if (val != 0x10000 && val != 0)
- 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_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_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_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_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_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));
+ case MISCREG_SOFTINT:
+ setReg(miscReg, val);;
+ if (val != 0x10000 && val != 0)
+ 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:
+ tc->getCpuPtr()->checkInterrupts = true;
+ tc->getCpuPtr()->post_interrupt(soft_interrupt);
+ 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_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 & PSTATE::ie && !(pstate & 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_HVER:
+ panic("Shouldn't be writing HVER\n");
+
+ case MISCREG_HINTP:
+ setReg(miscReg, val);
+
+ 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_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 | HPSTATE::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));
}
}
@@ -145,7 +146,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:
@@ -175,12 +176,12 @@ MiscRegFile::readFSRegWithEffect(int miscReg, ThreadContext * tc)
}
}
/*
- In Niagra STICK==TICK so this isn't needed
- case MISCREG_STICK:
- SparcSystem *sys;
- sys = dynamic_cast<SparcSystem*>(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<SparcSystem*>(tc->getSystemPtr());
+ assert(sys != NULL);
+ return curTick/Clock::Int::ns - sys->sysTick | (stick & ~(mask(63)));
*/
@@ -199,14 +200,17 @@ 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()->checkInterrupts = true;
- softint |= ULL(1) << 16;
+ if (!(tc->readMiscReg(MISCREG_STICK_CMPR) & (ULL(1) << 63))) {
+ tc->getCpuPtr()->post_interrupt(soft_interrupt);
+ tc->getCpuPtr()->checkInterrupts = true;
+ setRegWithEffect(MISCREG_SOFTINT, softint | (ULL(1) << 16), tc);
+ }
} else
sTickCompare->schedule(ticks * tc->getCpuPtr()->cycles(1) + curTick);
}
@@ -219,13 +223,17 @@ 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()->checkInterrupts = true;
+ if (!(tc->readMiscReg(MISCREG_HSTICK_CMPR) & (ULL(1) << 63))) {
+ setRegWithEffect(MISCREG_HINTP, 1, tc);
+ tc->getCpuPtr()->post_interrupt(hstick_match);
+ tc->getCpuPtr()->checkInterrupts = true;
+ }
// Need to do something to cause interrupt to happen here !!! @todo
} else
sTickCompare->schedule(ticks * tc->getCpuPtr()->cycles(1) + curTick);
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
@@ -363,6 +363,12 @@ BaseCPU::ProfileEvent::process()
}
void
+BaseCPU::post_interrupt(int int_type)
+{
+ interrupts.post(int_type);
+}
+
+void
BaseCPU::post_interrupt(int int_num, int index)
{
checkInterrupts = true;
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();