diff --git a/src/dev/x86/i82094aa.cc b/src/dev/x86/i82094aa.cc index ad9b29dd0..ed936d0cb 100644 --- a/src/dev/x86/i82094aa.cc +++ b/src/dev/x86/i82094aa.cc @@ -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, diff --git a/src/dev/x86/i82094aa.hh b/src/dev/x86/i82094aa.hh index e81d85fa9..c3a832aa9 100644 --- a/src/dev/x86/i82094aa.hh +++ b/src/dev/x86/i82094aa.hh @@ -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.