changeset 74f76480407f in /z/repo/m5
details: http://repo.m5sim.org/m5?cmd=changeset;node=74f76480407f
description:
        X86: Make the local APIC process interrupts and send them to the CPU.

diffstat:

3 files changed, 2 insertions(+), 14 deletions(-)
src/arch/x86/faults.hh     |    1 +
src/arch/x86/interrupts.cc |    7 +------
src/arch/x86/intmessage.hh |    8 --------

diffs (246 lines):

diff -r 340254de2031 -r 74f76480407f src/arch/x86/faults.hh
--- a/src/arch/x86/faults.hh    Sun Oct 12 13:44:24 2008 -0700
+++ b/src/arch/x86/faults.hh    Sun Oct 12 13:45:21 2008 -0700
@@ -215,9 +215,10 @@
 
     class NonMaskableInterrupt : public X86Interrupt
     {
+        uint8_t vector;
       public:
-        NonMaskableInterrupt() :
-            X86Interrupt("Non-Maskable-Interrupt", "#NMI")
+        NonMaskableInterrupt(uint8_t _vector) :
+            X86Interrupt("Non Maskable Interrupt", "#NMI"), vector(_vector)
         {}
     };
 
@@ -358,6 +359,23 @@
         {}
     };
 
+    class SystemManagementInterrupt : public X86Interrupt
+    {
+      public:
+        SystemManagementInterrupt() :
+            X86Interrupt("System Management Interrupt", "#SMI")
+        {}
+    };
+
+    class InitInterrupt : public X86Interrupt
+    {
+        uint8_t vector;
+      public:
+        InitInterrupt(uint8_t _vector) :
+            X86Interrupt("INIT Interrupt", "#INIT"), vector(_vector)
+        {}
+    };
+
     class SoftwareInterrupt : public X86Interrupt
     {
       public:
diff -r 340254de2031 -r 74f76480407f src/arch/x86/interrupts.cc
--- a/src/arch/x86/interrupts.cc        Sun Oct 12 13:44:24 2008 -0700
+++ b/src/arch/x86/interrupts.cc        Sun Oct 12 13:45:21 2008 -0700
@@ -259,12 +259,15 @@
             // Make sure we're really supposed to get this.
             assert((message.destMode == 0 && message.destination == id) ||
                    (bits((int)message.destination, id)));
-            if (DeliveryMode::isUnmaskable(message.deliveryMode)) {
-                DPRINTF(LocalApic, "Interrupt is an %s and unmaskable.\n",
-                        DeliveryMode::names[message.deliveryMode]);
-                panic("Unmaskable interrupts aren't implemented.\n");
-            } else if (DeliveryMode::isMaskable(message.deliveryMode)) {
-                DPRINTF(LocalApic, "Interrupt is an %s and maskable.\n",
+
+            /*
+             * Fixed and lowest-priority delivery mode interrupts are handled
+             * using the IRR/ISR registers, checking against the TPR, etc.
+             * The SMI, NMI, ExtInt, INIT, etc interrupts go straight through.
+             */
+            if (message.deliveryMode == DeliveryMode::Fixed ||
+                    message.deliveryMode == DeliveryMode::LowestPriority) {
+                DPRINTF(LocalApic, "Interrupt is an %s.\n",
                         DeliveryMode::names[message.deliveryMode]);
                 // Queue up the interrupt in the IRR.
                 if (vector > IRRV)
@@ -279,7 +282,27 @@
                         clearRegArrayBit(APIC_TRIGGER_MODE_BASE, vector);
                     }
                 }
-            }
+            } else if (!DeliveryMode::isReserved(message.deliveryMode)) {
+                DPRINTF(LocalApic, "Interrupt is an %s.\n",
+                        DeliveryMode::names[message.deliveryMode]);
+                if (message.deliveryMode == DeliveryMode::SMI &&
+                        !pendingSmi) {
+                    pendingUnmaskableInt = pendingSmi = true;
+                    smiMessage = message;
+                } else if (message.deliveryMode == DeliveryMode::NMI &&
+                        !pendingNmi) {
+                    pendingUnmaskableInt = pendingNmi = true;
+                    nmiMessage = message;
+                } else if (message.deliveryMode == DeliveryMode::ExtInt &&
+                        !pendingExtInt) {
+                    pendingExtInt = true;
+                    extIntMessage = message;
+                } else if (message.deliveryMode == DeliveryMode::INIT &&
+                        !pendingInit) {
+                    pendingUnmaskableInt = pendingInit = true;
+                    initMessage = message;
+                }
+            } 
         }
         break;
       default:
@@ -451,9 +474,14 @@
 X86ISA::Interrupts::check_interrupts(ThreadContext * tc) const
 {
     RFLAGS rflags = tc->readMiscRegNoEffect(MISCREG_RFLAGS);
-    if (IRRV > ISRV && rflags.intf &&
-            bits(IRRV, 7, 4) > bits(regs[APIC_TASK_PRIORITY], 7, 4)) {
+    if (pendingUnmaskableInt)
         return true;
+    if (rflags.intf) {
+        if (pendingExtInt)
+            return true;
+        if (IRRV > ISRV && bits(IRRV, 7, 4) >
+               bits(regs[APIC_TASK_PRIORITY], 7, 4))
+            return true;
     }
     return false;
 }
@@ -462,19 +490,52 @@
 X86ISA::Interrupts::getInterrupt(ThreadContext * tc)
 {
     assert(check_interrupts(tc));
-    return new ExternalInterrupt(IRRV);
+    // These are all probably fairly uncommon, so we'll make them easier to
+    // check for.
+    if (pendingUnmaskableInt) {
+        if (pendingSmi) {
+            return new SystemManagementInterrupt();
+        } else if (pendingNmi) {
+            return new NonMaskableInterrupt(nmiMessage.vector);
+        } else if (pendingInit) {
+            return new InitInterrupt(initMessage.vector);
+        } else {
+            panic("pendingUnmaskableInt set, but no unmaskable "
+                    "ints were pending.\n");
+            return NoFault;
+        }
+    } else if (pendingExtInt) {
+        return new ExternalInterrupt(extIntMessage.vector);
+    } else {
+        // The only thing left are fixed and lowest priority interrupts.
+        return new ExternalInterrupt(IRRV);
+    }
 }
 
 void
 X86ISA::Interrupts::updateIntrInfo(ThreadContext * tc)
 {
     assert(check_interrupts(tc));
-    // Mark the interrupt as "in service".
-    ISRV = IRRV;
-    setRegArrayBit(APIC_IN_SERVICE_BASE, ISRV);
-    // Clear it out of the IRR.
-    clearRegArrayBit(APIC_INTERRUPT_REQUEST_BASE, IRRV);
-    updateIRRV();
+    if (pendingUnmaskableInt) {
+        if (pendingSmi) {
+            pendingSmi = false;
+        } else if (pendingNmi) {
+            pendingNmi = false;
+        } else if (pendingInit) {
+            pendingInit = false;
+        }
+        if (!(pendingSmi || pendingNmi || pendingInit))
+            pendingUnmaskableInt = false;
+    } else if (pendingExtInt) {
+        pendingExtInt = false;
+    } else {
+        // Mark the interrupt as "in service".
+        ISRV = IRRV;
+        setRegArrayBit(APIC_IN_SERVICE_BASE, ISRV);
+        // Clear it out of the IRR.
+        clearRegArrayBit(APIC_INTERRUPT_REQUEST_BASE, IRRV);
+        updateIRRV();
+    }
 }
 
 X86ISA::Interrupts *
diff -r 340254de2031 -r 74f76480407f src/arch/x86/interrupts.hh
--- a/src/arch/x86/interrupts.hh        Sun Oct 12 13:44:24 2008 -0700
+++ b/src/arch/x86/interrupts.hh        Sun Oct 12 13:45:21 2008 -0700
@@ -60,6 +60,7 @@
 
 #include "arch/x86/apicregs.hh"
 #include "arch/x86/faults.hh"
+#include "arch/x86/intmessage.hh"
 #include "base/bitfield.hh"
 #include "cpu/thread_context.hh"
 #include "dev/io_device.hh"
@@ -97,6 +98,22 @@
     };
 
     ApicTimerEvent apicTimerEvent;
+
+    /*
+     * A set of variables to keep track of interrupts that don't go through
+     * the IRR.
+     */
+    bool pendingSmi;
+    TriggerIntMessage smiMessage;
+    bool pendingNmi;
+    TriggerIntMessage nmiMessage;
+    bool pendingExtInt;
+    TriggerIntMessage extIntMessage;
+    bool pendingInit;
+    TriggerIntMessage initMessage;
+
+    // This is a quick check whether any of the above (except ExtInt) are set.
+    bool pendingUnmaskableInt;
 
     /*
      * IRR and ISR maintenance.
@@ -207,7 +224,12 @@
      */
 
     Interrupts(Params * p) : BasicPioDevice(p), IntDev(this),
-                             latency(p->pio_latency), clock(0)
+                             latency(p->pio_latency), clock(0),
+                             pendingSmi(false), smiMessage(0),
+                             pendingNmi(false), nmiMessage(0),
+                             pendingExtInt(false), extIntMessage(0),
+                             pendingInit(false), initMessage(0),
+                             pendingUnmaskableInt(false)
     {
         pioSize = PageBytes;
         memset(regs, 0, sizeof(regs));
diff -r 340254de2031 -r 74f76480407f src/arch/x86/intmessage.hh
--- a/src/arch/x86/intmessage.hh        Sun Oct 12 13:44:24 2008 -0700
+++ b/src/arch/x86/intmessage.hh        Sun Oct 12 13:45:21 2008 -0700
@@ -66,22 +66,9 @@
         };
 
         static inline bool
-        isUnmaskable(int mode)
-        {
-            return (mode == SMI || mode == NMI ||
-                    mode == INIT || mode == ExtInt);
-        }
-
-        static inline bool
-        isMaskable(int mode)
-        {
-            return (mode == Fixed || mode == LowestPriority);
-        }
-
-        static inline bool
         isReserved(int mode)
         {
-            return !(isMaskable(mode) || isUnmaskable(mode));
+            return mode == 3 || mode == 6;
         }
     }
 
_______________________________________________
m5-dev mailing list
[email protected]
http://m5sim.org/mailman/listinfo/m5-dev

Reply via email to