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++) {
}
}
- 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);
-
- return std::make_shared<InterruptFault>();
- } else {
- return NoFault;
+ 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);
+ }
}
+
+ 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
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);
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);
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)
}
-
-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);
// 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
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
Fault
getInterrupt(ThreadContext *tc)
{
+ assert(checkInterrupts(tc));
panic("Interrupts::getInterrupt not implemented.\n");
}
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);