X86: Implement lowest priority interrupts more correctly.
authorGabe Black <gblack@eecs.umich.edu>
Sun, 26 Apr 2009 09:09:54 +0000 (02:09 -0700)
committerGabe Black <gblack@eecs.umich.edu>
Sun, 26 Apr 2009 09:09:54 +0000 (02:09 -0700)
Lowest priority interrupts are now delivered based on a rotating offset into
the list of potential recipients. There could be parasitic cases were a
processor gets picked on and ends up at that rotating offset all the time, but
it's much more likely that the group will stay consistent and the pain will be
distributed evenly.

src/dev/x86/i82094aa.cc
src/dev/x86/i82094aa.hh

index ad9b29dd05cade9fa95b06facb73e0631e68dc12..ed936d0cb7df17e8e001374fa73466d9141e40f1 100644 (file)
@@ -38,7 +38,7 @@
 
 X86ISA::I82094AA::I82094AA(Params *p) : PioDevice(p), IntDev(this),
     latency(p->pio_latency), pioAddr(p->pio_addr),
-    extIntPic(p->external_int_pic)
+    extIntPic(p->external_int_pic), lowestPriorityOffset(0)
 {
     // This assumes there's only one I/O APIC in the system
     initialApicId = id = p->apic_id;
@@ -189,8 +189,22 @@ X86ISA::I82094AA::signalInterrupt(int line)
                     apics.push_back(localApicIt->first);
                 }
             }
-            if (message.deliveryMode == DeliveryMode::LowestPriority) {
-                panic("Lowest priority delivery mode is not implemented.\n");
+            if (message.deliveryMode == DeliveryMode::LowestPriority &&
+                    apics.size()) {
+                // The manual seems to suggest that the chipset just does
+                // something reasonable for these instead of actually using
+                // state from the local APIC. We'll just rotate an offset
+                // through the set of APICs selected above.
+                uint64_t modOffset = lowestPriorityOffset % apics.size();
+                lowestPriorityOffset++;
+                ApicList::iterator apicIt = apics.begin();
+                while (modOffset--) {
+                    apicIt++;
+                    assert(apicIt != apics.end());
+                }
+                int selected = *apicIt;
+                apics.clear();
+                apics.push_back(selected);
             }
         }
         intPort->sendMessage(apics, message,
index e81d85fa9c9ef765e3585df123eb4a7cc1225fb8..c3a832aa944f2a84801165ce82ab6e6d512404f5 100644 (file)
@@ -77,6 +77,8 @@ class I82094AA : public PioDevice, public IntDev
     uint8_t id;
     uint8_t arbId;
 
+    uint64_t lowestPriorityOffset;
+
     static const uint8_t TableSize = 24;
     // This implementation is based on version 0x11, but 0x14 avoids having
     // to deal with the arbitration and APIC bus guck.