changeset 340254de2031 in /z/repo/m5
details: http://repo.m5sim.org/m5?cmd=changeset;node=340254de2031
description:
        X86: Make the local APIC handle interrupt messages from the IO APIC.

diffstat:

5 files changed, 22 insertions(+), 12 deletions(-)
src/arch/x86/faults.hh     |    1 +
src/arch/x86/interrupts.cc |    1 +
src/arch/x86/intmessage.hh |   19 +++++++++++++++++++
src/dev/x86/i82094aa.cc    |   12 +-----------
src/dev/x86/i8259.hh       |    1 -

diffs (truncated from 457 to 300 lines):

diff -r b87e45d7c585 -r 340254de2031 src/arch/x86/faults.hh
--- a/src/arch/x86/faults.hh    Sun Oct 12 13:35:26 2008 -0700
+++ b/src/arch/x86/faults.hh    Sun Oct 12 13:44:24 2008 -0700
@@ -351,9 +351,10 @@
 
     class ExternalInterrupt : public X86Interrupt
     {
+        uint8_t vector;
       public:
-        ExternalInterrupt() :
-            X86Interrupt("External Interrupt", "#INTR")
+        ExternalInterrupt(uint8_t _vector) :
+            X86Interrupt("External Interrupt", "#INTR"), vector(_vector)
         {}
     };
 
diff -r b87e45d7c585 -r 340254de2031 src/arch/x86/interrupts.cc
--- a/src/arch/x86/interrupts.cc        Sun Oct 12 13:35:26 2008 -0700
+++ b/src/arch/x86/interrupts.cc        Sun Oct 12 13:44:24 2008 -0700
@@ -57,7 +57,9 @@
 
 #include "arch/x86/apicregs.hh"
 #include "arch/x86/interrupts.hh"
+#include "arch/x86/intmessage.hh"
 #include "cpu/base.hh"
+#include "mem/packet_access.hh"
 
 int
 divideFromConf(uint32_t conf)
@@ -242,12 +244,43 @@
 Tick
 X86ISA::Interrupts::recvMessage(PacketPtr pkt)
 {
-    Addr offset = pkt->getAddr() - x86InterruptAddress(0, 0);
+    uint8_t id = 0;
+    Addr offset = pkt->getAddr() - x86InterruptAddress(id, 0);
     assert(pkt->cmd == MemCmd::MessageReq);
     switch(offset)
     {
       case 0:
-        DPRINTF(LocalApic, "Got Trigger Interrupt message.\n");
+        {
+            TriggerIntMessage message = pkt->get<TriggerIntMessage>();
+            uint8_t vector = message.vector;
+            DPRINTF(LocalApic,
+                    "Got Trigger Interrupt message with vector %#x.\n",
+                    vector);
+            // 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",
+                        DeliveryMode::names[message.deliveryMode]);
+                // Queue up the interrupt in the IRR.
+                if (vector > IRRV)
+                    IRRV = vector;
+                if (!getRegArrayBit(APIC_INTERRUPT_REQUEST_BASE, vector)) {
+                    setRegArrayBit(APIC_INTERRUPT_REQUEST_BASE, vector);
+                    if (message.trigger) {
+                        // Level triggered.
+                        setRegArrayBit(APIC_TRIGGER_MODE_BASE, vector);
+                    } else {
+                        // Edge triggered.
+                        clearRegArrayBit(APIC_TRIGGER_MODE_BASE, vector);
+                    }
+                }
+            }
+        }
         break;
       default:
         panic("Local apic got unknown interrupt message at offset %#x.\n",
@@ -414,6 +447,36 @@
     return;
 }
 
+bool
+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)) {
+        return true;
+    }
+    return false;
+}
+
+Fault
+X86ISA::Interrupts::getInterrupt(ThreadContext * tc)
+{
+    assert(check_interrupts(tc));
+    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();
+}
+
 X86ISA::Interrupts *
 X86LocalApicParams::create()
 {
diff -r b87e45d7c585 -r 340254de2031 src/arch/x86/interrupts.hh
--- a/src/arch/x86/interrupts.hh        Sun Oct 12 13:35:26 2008 -0700
+++ b/src/arch/x86/interrupts.hh        Sun Oct 12 13:44:24 2008 -0700
@@ -60,6 +60,7 @@
 
 #include "arch/x86/apicregs.hh"
 #include "arch/x86/faults.hh"
+#include "base/bitfield.hh"
 #include "cpu/thread_context.hh"
 #include "dev/io_device.hh"
 #include "dev/x86/intdev.hh"
@@ -74,7 +75,12 @@
 class Interrupts : public BasicPioDevice, IntDev
 {
   protected:
+    // Storage for the APIC registers
     uint32_t regs[NUM_APIC_REGS];
+
+    /*
+     * Timing related stuff.
+     */
     Tick latency;
     Tick clock;
 
@@ -92,7 +98,58 @@
 
     ApicTimerEvent apicTimerEvent;
 
+    /*
+     * IRR and ISR maintenance.
+     */
+    uint8_t IRRV;
+    uint8_t ISRV;
+
+    int
+    findRegArrayMSB(ApicRegIndex base)
+    {
+        int offset = 7;
+        do {
+            if (regs[base + offset] != 0) {
+                return offset * 32 + findMsbSet(regs[base + offset]);
+            }
+        } while (offset--);
+        return 0;
+    }
+
+    void
+    updateIRRV()
+    {
+        IRRV = findRegArrayMSB(APIC_INTERRUPT_REQUEST_BASE);
+    }
+
+    void
+    updateISRV()
+    {
+        ISRV = findRegArrayMSB(APIC_IN_SERVICE_BASE);
+    }
+
+    void
+    setRegArrayBit(ApicRegIndex base, uint8_t vector)
+    {
+        regs[base + (vector % 32)] |= (1 << (vector >> 5));
+    }
+
+    void
+    clearRegArrayBit(ApicRegIndex base, uint8_t vector)
+    {
+        regs[base + (vector % 32)] &= ~(1 << (vector >> 5));
+    }
+
+    bool
+    getRegArrayBit(ApicRegIndex base, uint8_t vector)
+    {
+        return bits(regs[base + (vector % 32)], vector >> 5);
+    }
+
   public:
+    /*
+     * Params stuff.
+     */
     typedef X86LocalApicParams Params;
 
     void setClock(Tick newClock)
@@ -106,6 +163,9 @@
         return dynamic_cast<const Params *>(_params);
     }
 
+    /*
+     * Functions to interact with the interrupt port from IntDev.
+     */
     Tick read(PacketPtr pkt);
     Tick write(PacketPtr pkt);
     Tick recvMessage(PacketPtr pkt);
@@ -124,6 +184,17 @@
                     x86InterruptAddress(0, 0) + PhysAddrAPICRangeSize));
     }
 
+    Port *getPort(const std::string &if_name, int idx = -1)
+    {
+        if (if_name == "int_port")
+            return intPort;
+        return BasicPioDevice::getPort(if_name, idx);
+    }
+
+    /*
+     * Functions to access and manipulate the APIC's registers.
+     */
+
     uint32_t readReg(ApicRegIndex miscReg);
     void setReg(ApicRegIndex reg, uint32_t val);
     void setRegNoEffect(ApicRegIndex reg, uint32_t val)
@@ -131,58 +202,32 @@
         regs[reg] = val;
     }
 
+    /*
+     * Constructor.
+     */
+
     Interrupts(Params * p) : BasicPioDevice(p), IntDev(this),
                              latency(p->pio_latency), clock(0)
     {
         pioSize = PageBytes;
+        memset(regs, 0, sizeof(regs));
         //Set the local apic DFR to the flat model.
         regs[APIC_DESTINATION_FORMAT] = (uint32_t)(-1);
-        memset(regs, 0, sizeof(regs));
-        clear_all();
+        ISRV = 0;
+        IRRV = 0;
     }
 
-    Port *getPort(const std::string &if_name, int idx = -1)
-    {
-        if (if_name == "int_port")
-            return intPort;
-        return BasicPioDevice::getPort(if_name, idx);
-    }
+    /*
+     * Functions for retrieving interrupts for the CPU to handle.
+     */
 
-    int InterruptLevel(uint64_t softint)
-    {
-        panic("Interrupts::InterruptLevel unimplemented!\n");
-        return 0;
-    }
+    bool check_interrupts(ThreadContext * tc) const;
+    Fault getInterrupt(ThreadContext * tc);
+    void updateIntrInfo(ThreadContext * tc);
 
-    void post(int int_num, int index)
-    {
-        panic("Interrupts::post unimplemented!\n");
-    }
-
-    void clear(int int_num, int index)
-    {
-        warn("Interrupts::clear unimplemented!\n");
-    }
-
-    void clear_all()
-    {
-        warn("Interrupts::clear_all unimplemented!\n");
-    }
-
-    bool check_interrupts(ThreadContext * tc) const
-    {
-        return false;
-    }
-
-    Fault getInterrupt(ThreadContext * tc)
-    {
-        return NoFault;
-    }
-
-    void updateIntrInfo(ThreadContext * tc)
-    {
-        panic("Interrupts::updateIntrInfo unimplemented!\n");
-    }
+    /*
+     * Serialization.
+     */
 
     void serialize(std::ostream & os)
     {
@@ -193,6 +238,25 @@
     {
_______________________________________________
m5-dev mailing list
[email protected]
http://m5sim.org/mailman/listinfo/m5-dev

Reply via email to