diff --git a/src/arch/x86/interrupts.cc b/src/arch/x86/interrupts.cc index 88d200b80..1b7933036 100644 --- a/src/arch/x86/interrupts.cc +++ b/src/arch/x86/interrupts.cc @@ -510,11 +510,41 @@ X86ISA::Interrupts::setReg(ApicRegIndex reg, uint32_t val) bool timing = sys->getMemoryMode() == Enums::timing; // Be careful no updates of the delivery status bit get lost. regs[APIC_INTERRUPT_COMMAND_LOW] = low; + ApicList apics; + int numContexts = sys->numContexts(); switch (low.destShorthand) { case 0: - pendingIPIs++; - intPort->sendMessage(message, timing); - newVal = regs[APIC_INTERRUPT_COMMAND_LOW]; + if (message.deliveryMode == DeliveryMode::LowestPriority) { + panic("Lowest priority delivery mode " + "IPIs aren't implemented.\n"); + } + if (message.destMode == 1) { + int dest = message.destination; + hack_once("Assuming logical destinations are 1 << id.\n"); + for (int i = 0; i < numContexts; i++) { + if (dest & 0x1) + apics.push_back(i); + dest = dest >> 1; + } + } else { + if (message.destination == 0xFF) { + for (int i = 0; i < numContexts; i++) { + if (i == initialApicId) { + requestInterrupt(message.vector, + message.deliveryMode, message.trigger); + } else { + apics.push_back(i); + } + } + } else { + if (message.destination == initialApicId) { + requestInterrupt(message.vector, + message.deliveryMode, message.trigger); + } else { + apics.push_back(message.destination); + } + } + } break; case 1: newVal = val; @@ -527,22 +557,17 @@ X86ISA::Interrupts::setReg(ApicRegIndex reg, uint32_t val) // Fall through case 3: { - int numContexts = sys->numContexts(); - pendingIPIs += (numContexts - 1); for (int i = 0; i < numContexts; i++) { - int thisId = sys->getThreadContext(i)->contextId(); - if (thisId != initialApicId) { - PacketPtr pkt = buildIntRequest(thisId, message); - if (timing) - intPort->sendMessageTiming(pkt, latency); - else - intPort->sendMessageAtomic(pkt); + if (i != initialApicId) { + apics.push_back(i); } } } - newVal = regs[APIC_INTERRUPT_COMMAND_LOW]; break; } + pendingIPIs += apics.size(); + intPort->sendMessage(apics, message, timing); + newVal = regs[APIC_INTERRUPT_COMMAND_LOW]; } break; case APIC_LVT_TIMER: diff --git a/src/dev/x86/i82094aa.cc b/src/dev/x86/i82094aa.cc index 3f0ed9e96..ad9b29dd0 100644 --- a/src/dev/x86/i82094aa.cc +++ b/src/dev/x86/i82094aa.cc @@ -28,6 +28,7 @@ * Authors: Gabe Black */ +#include "arch/x86/interrupts.hh" #include "arch/x86/intmessage.hh" #include "dev/x86/i82094aa.hh" #include "dev/x86/i8259.hh" @@ -162,7 +163,38 @@ X86ISA::I82094AA::signalInterrupt(int line) message.destMode = entry.destMode; message.level = entry.polarity; message.trigger = entry.trigger; - intPort->sendMessage(message, sys->getMemoryMode() == Enums::timing); + ApicList apics; + int numContexts = sys->numContexts(); + if (message.destMode == 0) { + if (message.deliveryMode == DeliveryMode::LowestPriority) { + panic("Lowest priority delivery mode from the " + "IO APIC aren't supported in physical " + "destination mode.\n"); + } + if (message.destination == 0xFF) { + for (int i = 0; i < numContexts; i++) { + apics.push_back(i); + } + } else { + apics.push_back(message.destination); + } + } else { + for (int i = 0; i < numContexts; i++) { + std::map::iterator localApicIt = + localApics.find(i); + assert(localApicIt != localApics.end()); + Interrupts *localApic = localApicIt->second; + if ((localApic->readReg(APIC_LOGICAL_DESTINATION) >> 24) & + message.destination) { + apics.push_back(localApicIt->first); + } + } + if (message.deliveryMode == DeliveryMode::LowestPriority) { + panic("Lowest priority delivery mode is not implemented.\n"); + } + } + intPort->sendMessage(apics, message, + sys->getMemoryMode() == Enums::timing); } } diff --git a/src/dev/x86/intdev.cc b/src/dev/x86/intdev.cc index 10e50c13e..5bc6065f5 100644 --- a/src/dev/x86/intdev.cc +++ b/src/dev/x86/intdev.cc @@ -31,50 +31,16 @@ #include "dev/x86/intdev.hh" void -X86ISA::IntDev::IntPort::sendMessage(TriggerIntMessage message, bool timing) +X86ISA::IntDev::IntPort::sendMessage(ApicList apics, + TriggerIntMessage message, bool timing) { - if (DeliveryMode::isReserved(message.deliveryMode)) { - fatal("Tried to use reserved delivery mode %d\n", - message.deliveryMode); - } else if (DTRACE(IntDev)) { - DPRINTF(IntDev, "Delivery mode is: %s.\n", - DeliveryMode::names[message.deliveryMode]); - DPRINTF(IntDev, "Vector is %#x.\n", message.vector); - } - if (message.destMode == 0) { - DPRINTF(IntDev, - "Sending interrupt to APIC ID %d.\n", message.destination); - PacketPtr pkt = buildIntRequest(message.destination, message); - if (timing) { + ApicList::iterator apicIt; + for (apicIt = apics.begin(); apicIt != apics.end(); apicIt++) { + PacketPtr pkt = buildIntRequest(*apicIt, message); + if (timing) sendMessageTiming(pkt, latency); - } else { + else sendMessageAtomic(pkt); - } - } else { - DPRINTF(IntDev, "Sending interrupts to APIC IDs:" - "%s%s%s%s%s%s%s%s\n", - bits((int)message.destination, 0) ? " 0": "", - bits((int)message.destination, 1) ? " 1": "", - bits((int)message.destination, 2) ? " 2": "", - bits((int)message.destination, 3) ? " 3": "", - bits((int)message.destination, 4) ? " 4": "", - bits((int)message.destination, 5) ? " 5": "", - bits((int)message.destination, 6) ? " 6": "", - bits((int)message.destination, 7) ? " 7": "" - ); - uint8_t dests = message.destination; - uint8_t id = 0; - while(dests) { - if (dests & 0x1) { - PacketPtr pkt = buildIntRequest(id, message); - if (timing) - sendMessageTiming(pkt, latency); - else - sendMessageAtomic(pkt); - } - dests >>= 1; - id++; - } } } diff --git a/src/dev/x86/intdev.hh b/src/dev/x86/intdev.hh index 3a99783f7..c2c8057b9 100644 --- a/src/dev/x86/intdev.hh +++ b/src/dev/x86/intdev.hh @@ -43,8 +43,12 @@ #include "params/X86IntSinkPin.hh" #include "params/X86IntLine.hh" +#include + namespace X86ISA { +typedef std::list ApicList; + class IntDev { protected: @@ -78,7 +82,8 @@ class IntDev // This is x86 focused, so if this class becomes generic, this would // need to be moved into a subclass. - void sendMessage(TriggerIntMessage message, bool timing); + void sendMessage(ApicList apics, + TriggerIntMessage message, bool timing); void recvStatusChange(Status status) {