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.hh134
1 files changed, 116 insertions, 18 deletions
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)