summaryrefslogtreecommitdiff
path: root/src/dev/x86
diff options
context:
space:
mode:
Diffstat (limited to 'src/dev/x86')
-rw-r--r--src/dev/x86/i82094aa.cc20
-rw-r--r--src/dev/x86/i82094aa.hh2
2 files changed, 19 insertions, 3 deletions
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.