diff options
author | Mitch Hayenga <mitch.hayenga@arm.com> | 2016-07-21 17:19:15 +0100 |
---|---|---|
committer | Mitch Hayenga <mitch.hayenga@arm.com> | 2016-07-21 17:19:15 +0100 |
commit | 8a476d387c84f037d0ccf3cc20dc88870ab45fec (patch) | |
tree | 341d4975740d91056a44b13bd43e10bf175d7166 /src/arch/alpha | |
parent | d25b58036a040d8ac733b824e2865e1f5fe43e00 (diff) | |
download | gem5-8a476d387c84f037d0ccf3cc20dc88870ab45fec.tar.xz |
isa: Modify get/check interrupt routines
Make it so that getInterrupt *always* returns an interrupt if
checkInterrupts() returns true. This fixes/simplifies handling
of interrupts on the SMT FS CPUs (currently minor).
Diffstat (limited to 'src/arch/alpha')
-rw-r--r-- | src/arch/alpha/interrupts.hh | 68 |
1 files changed, 46 insertions, 22 deletions
diff --git a/src/arch/alpha/interrupts.hh b/src/arch/alpha/interrupts.hh index 1e67f54b5..61ac6c968 100644 --- a/src/arch/alpha/interrupts.hh +++ b/src/arch/alpha/interrupts.hh @@ -137,18 +137,18 @@ class Interrupts : public SimObject 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++) { @@ -160,28 +160,52 @@ class Interrupts : public SimObject } } - 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 |